diff options
Diffstat (limited to 'SmartDeviceLinkTests/DevAPISpecs')
25 files changed, 2536 insertions, 626 deletions
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m index e538122f5..1341fc916 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m @@ -2,6 +2,7 @@ #import <Nimble/Nimble.h> #import "SDLAudioStreamManager.h" +#import "SDLError.h" #import "SDLStreamingAudioManagerMock.h" QuickSpecBegin(SDLAudioStreamManagerSpec) @@ -32,8 +33,6 @@ describe(@"the audio stream manager", ^{ beforeEach(^{ mockAudioManager.audioConnected = NO; [testManager pushWithFileURL:testAudioFileURL]; - - [NSThread sleepForTimeInterval:0.5]; }); describe(@"after attempting to play the file", ^{ @@ -43,7 +42,7 @@ describe(@"the audio stream manager", ^{ }); it(@"should fail to send data", ^{ - expect(mockAudioManager.dataSinceClear.length).to(equal(0)); + expect(mockAudioManager.dataSinceClear.length).toEventually(equal(0)); expect(mockAudioManager.error.code).toEventually(equal(SDLAudioStreamManagerErrorNotConnected)); }); }); @@ -53,8 +52,6 @@ describe(@"the audio stream manager", ^{ beforeEach(^{ mockAudioManager.audioConnected = NO; [testManager pushWithData:testAudioFileData]; - - [NSThread sleepForTimeInterval:0.5]; }); describe(@"after attempting to play the file", ^{ @@ -64,7 +61,7 @@ describe(@"the audio stream manager", ^{ }); it(@"should fail to send data", ^{ - expect(mockAudioManager.dataSinceClear.length).to(equal(0)); + expect(mockAudioManager.dataSinceClear.length).toEventually(equal(0)); expect(mockAudioManager.error.code).toEventually(equal(SDLAudioStreamManagerErrorNotConnected)); }); }); @@ -75,27 +72,27 @@ describe(@"the audio stream manager", ^{ beforeEach(^{ mockAudioManager.audioConnected = YES; [testManager pushWithFileURL:testAudioFileURL]; - - [NSThread sleepForTimeInterval:0.5]; }); it(@"should have a file in the queue", ^{ - expect(testManager.queue).toNot(beEmpty()); + expect(testManager.queue).toEventuallyNot(beEmpty()); }); describe(@"after attempting to play the file", ^{ beforeEach(^{ [mockAudioManager clearData]; [testManager playNextWhenReady]; - - [NSThread sleepForTimeInterval:1.0]; }); it(@"should be sending data", ^{ expect(testManager.isPlaying).toEventually(beTrue()); expect(mockAudioManager.dataSinceClear.length).toEventually(equal(34380)); - // Fails when it shouldn't, `weakself` goes to nil in `sdl_playNextWhenReady` + // wait for the delegate to be called when the audio finishes + float waitTime = 1.1 + 0.25; // length of audio in testAudioFileURL + 0.25 buffer + NSLog(@"Please wait %f for audio file to finish playing...", waitTime); + [NSThread sleepForTimeInterval:waitTime]; + expect(mockAudioManager.finishedPlaying).toEventually(beTrue()); }); }); @@ -115,12 +112,10 @@ describe(@"the audio stream manager", ^{ beforeEach(^{ mockAudioManager.audioConnected = YES; [testManager pushWithData:testAudioFileData]; - - [NSThread sleepForTimeInterval:0.5]; }); it(@"should have a file in the queue", ^{ - expect(testManager.queue).toNot(beEmpty()); + expect(testManager.queue).toEventuallyNot(beEmpty()); }); describe(@"after attempting to play the audio buffer", ^{ diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m index 40edaeed3..47156d1c0 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m @@ -95,7 +95,7 @@ describe(@"choice set manager tests", ^{ testCell3 = [[SDLChoiceCell alloc] initWithText:@"test3"]; enabledWindowCapability = [[SDLWindowCapability alloc] init]; - enabledWindowCapability.textFields = @[[[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetType5 width:500 rows:1]]; + enabledWindowCapability.textFields = @[[[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetUtf8 width:500 rows:1]]; disabledWindowCapability = [[SDLWindowCapability alloc] init]; disabledWindowCapability.textFields = @[]; blankWindowCapability = [[SDLWindowCapability alloc] init]; @@ -216,6 +216,11 @@ describe(@"choice set manager tests", ^{ it(@"should shutdown", ^{ expect(testManager.currentState).to(equal(SDLChoiceManagerStateShutdown)); + expect(testManager.vrOptional).to(beTrue()); + expect(testManager.currentHMILevel).to(equal(SDLHMILevelNone)); + expect(testManager.pendingPresentationSet).to(beNil()); + expect(testManager.preloadedMutableChoices).to(beEmpty()); + expect(testManager.pendingMutablePreloadChoices).to(beEmpty()); }); }); }); @@ -273,6 +278,34 @@ describe(@"choice set manager tests", ^{ expect(testManager.pendingPreloadChoices).to(haveCount(1)); }); }); + + context(@"when the manager shuts down during preloading", ^{ + beforeEach(^{ + testManager.pendingMutablePreloadChoices = [NSMutableSet setWithArray:@[testCell1]]; + + [testManager preloadChoices:@[testCell1, testCell2, testCell3] withCompletionHandler:^(NSError * _Nullable error) { + }]; + }); + + it(@"should leave the list of pending and uploaded choice items empty when the operation finishes", ^{ + expect(testManager.pendingPreloadChoices).to(contain(testCell1)); + expect(testManager.pendingPreloadChoices).to(contain(testCell2)); + expect(testManager.pendingPreloadChoices).to(contain(testCell3)); + expect(testManager.transactionQueue.operations.firstObject).to(beAnInstanceOf([SDLPreloadChoicesOperation class])); + + [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO]; + testManager.pendingMutablePreloadChoices = [NSMutableSet set]; + testManager.preloadedMutableChoices = [NSMutableSet set]; + + SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject; + testOp.completionBlock(); + + expect(testManager.preloadedMutableChoices).to(beEmpty()); + expect(testManager.preloadedChoices).to(beEmpty()); + expect(testManager.pendingMutablePreloadChoices).to(beEmpty()); + expect(testManager.pendingPreloadChoices).to(beEmpty()); + }); + }); }); describe(@"deleting choices", ^{ @@ -321,6 +354,40 @@ describe(@"choice set manager tests", ^{ expect(testManager.transactionQueue.operationCount).to(equal(1)); // No delete operation }); }); + + context(@"when the manager shuts down during deletion", ^{ + __block SDLPresentChoiceSetOperation *pendingPresentOp = nil; + __block id<SDLChoiceSetDelegate> choiceDelegate = nil; + + beforeEach(^{ + choiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate)); + pendingPresentOp = OCMClassMock([SDLPresentChoiceSetOperation class]); + OCMStub(pendingPresentOp.choiceSet.choices).andReturn([NSSet setWithArray:@[testCell1]]); + testManager.pendingPresentOperation = pendingPresentOp; + testManager.pendingPresentationSet = [[SDLChoiceSet alloc] initWithTitle:@"Test" delegate:choiceDelegate choices:@[testCell1]]; + testManager.preloadedMutableChoices = [NSMutableSet setWithObject:testCell1]; + + [testManager deleteChoices:@[testCell1, testCell2, testCell3]]; + }); + + it(@"should leave the list of pending and uploaded choice items empty when the operation finishes", ^{ + expect(testManager.transactionQueue.operations.lastObject).to(beAnInstanceOf([SDLDeleteChoicesOperation class])); + expect(testManager.pendingPresentationSet).to(beNil()); + OCMVerify([pendingPresentOp cancel]); + OCMVerify([choiceDelegate choiceSet:[OCMArg any] didReceiveError:[OCMArg any]]); + + [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO]; + testManager.pendingMutablePreloadChoices = [NSMutableSet set]; + testManager.preloadedMutableChoices = [NSMutableSet set]; + + testManager.transactionQueue.operations.lastObject.completionBlock(); + + expect(testManager.preloadedMutableChoices).to(beEmpty()); + expect(testManager.preloadedChoices).to(beEmpty()); + expect(testManager.pendingMutablePreloadChoices).to(beEmpty()); + expect(testManager.pendingPreloadChoices).to(beEmpty()); + }); + }); }); describe(@"presenting a choice set", ^{ @@ -400,6 +467,30 @@ describe(@"choice set manager tests", ^{ }); }); }); + + describe(@"when the manager shuts down during presentation", ^{ + beforeEach(^{ + [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate]; + }); + + it(@"should leave the list of pending and uploaded choice items empty when the operation finishes", ^{ + expect(testManager.pendingPresentationSet).to(equal(testChoiceSet)); + expect(testManager.transactionQueue.operations).to(haveCount(2)); + expect(testManager.transactionQueue.operations.firstObject).to(beAnInstanceOf([SDLPreloadChoicesOperation class])); + expect(testManager.transactionQueue.operations.lastObject).to(beAnInstanceOf([SDLPresentChoiceSetOperation class])); + + [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO]; + testManager.pendingMutablePreloadChoices = [NSMutableSet set]; + testManager.preloadedMutableChoices = [NSMutableSet set]; + + testManager.transactionQueue.operations.lastObject.completionBlock(); + + expect(testManager.preloadedMutableChoices).to(beEmpty()); + expect(testManager.preloadedChoices).to(beEmpty()); + expect(testManager.pendingMutablePreloadChoices).to(beEmpty()); + expect(testManager.pendingPreloadChoices).to(beEmpty()); + }); + }); }); describe(@"presenting a keyboard", ^{ diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m index 38fb36ec9..73a973975 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m @@ -79,7 +79,10 @@ describe(@"a configuration", ^{ }); it(@"configurationWithLifecycle:lockScreen:logging:fileManager", ^{ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" testConfig = [SDLConfiguration configurationWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig fileManager:someFileManagerConfig]; + #pragma clang diagnostic pop expect(testConfig.lifecycleConfig).to(equal(someLifecycleConfig)); expect(testConfig.lockScreenConfig).to(equal(someLockscreenConfig)); @@ -131,7 +134,10 @@ describe(@"a configuration", ^{ }); it(@"configurationWithLifecycle:lockScreen:logging:streamingMedia:fileManager:", ^{ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" testConfig = [SDLConfiguration configurationWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig streamingMedia:someStreamingConfig fileManager:someFileManagerConfig]; + #pragma clang diagnostic pop expect(testConfig.lifecycleConfig).to(equal(someLifecycleConfig)); expect(testConfig.lockScreenConfig).to(equal(someLockscreenConfig)); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m index e50dab063..81673c819 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m @@ -31,7 +31,7 @@ } + (NSSet<NSString *> *)availableMakes { - return [NSSet set]; + return [NSSet setWithObject:@"SDL"]; } @end diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h index e6e9bae11..b0cf5a985 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h @@ -12,6 +12,4 @@ @interface SDLFakeViewControllerPresenter : NSObject <SDLViewControllerPresentable> -@property (strong, nonatomic, nullable) UIViewController *lockViewController; - @end diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m index db28e24b8..c4c7fe101 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m @@ -12,6 +12,7 @@ @interface SDLFakeViewControllerPresenter () @property (assign, nonatomic) BOOL shouldShowLockScreen; +@property (strong, nonatomic, nullable) UIViewController *lockVC; @end @@ -45,5 +46,12 @@ } } +- (void)setLockViewController:(UIViewController *)lockViewController { + self.lockVC = lockViewController; +} + +- (UIViewController *)lockViewController { + return self.lockVC; +} @end diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m index 4e136dfa0..55bc7336f 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m @@ -12,6 +12,7 @@ #import "SDLGlobals.h" #import "SDLHMILevel.h" #import "SDLLifecycleConfiguration.h" +#import "SDLLifecycleProtocolHandler.h" #import "SDLLockScreenConfiguration.h" #import "SDLLockScreenManager.h" #import "SDLLogConfiguration.h" @@ -23,12 +24,12 @@ #import "SDLOnHMIStatus.h" #import "SDLPerformAppServiceInteractionResponse.h" #import "SDLPermissionManager.h" -#import "SDLProxy.h" #import "SDLProtocol.h" #import "SDLRegisterAppInterface.h" #import "SDLRegisterAppInterfaceResponse.h" #import "SDLResult.h" #import "SDLRPCNotificationNotification.h" +#import "SDLSecondaryTransportManager.h" #import "SDLShow.h" #import "SDLStateMachine.h" #import "SDLStreamingMediaConfiguration.h" @@ -41,15 +42,26 @@ #import "SDLVersion.h" #import "SDLVideoStreamingState.h" +#import "TestOldConfigurationUpdateManagerDelegate.h" +#import "TestNewConfigurationUpdateManagerDelegate.h" + // Ignore the deprecated proxy methods #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +@interface SDLStreamingMediaManager () + +@property (strong, nonatomic, nullable) SDLSecondaryTransportManager *secondaryTransportManager; +- (void)startSecondaryTransportWithProtocol:(SDLProtocol *)protocol; + +@end + @interface SDLLifecycleManager () // this private property is used for testing @property (copy, nonatomic) dispatch_queue_t lifecycleQueue; @property (assign, nonatomic) int32_t lastCorrelationId; +@property (strong, nonatomic) SDLLanguage currentVRLanguage; @end QuickConfigurationBegin(SendingRPCsConfiguration) @@ -69,10 +81,15 @@ QuickConfigurationBegin(SendingRPCsConfiguration) QuickConfigurationEnd +@interface SDLGlobals () +@property (copy, nonatomic, readwrite) SDLVersion *protocolVersion; +@end + @interface SDLLifecycleManager () // reach the private property for testing @property (strong, nonatomic, nullable) SDLSecondaryTransportManager *secondaryTransportManager; +@property (strong, nonatomic, nullable) SDLLifecycleProtocolHandler *protocolHandler; @end @@ -83,13 +100,13 @@ describe(@"a lifecycle manager", ^{ __block SDLConfiguration *testConfig = nil; __block id protocolMock = OCMClassMock([SDLProtocol class]); - __block id proxyMock = OCMClassMock([SDLProxy class]); __block id lockScreenManagerMock = OCMClassMock([SDLLockScreenManager class]); __block id fileManagerMock = OCMClassMock([SDLFileManager class]); __block id permissionManagerMock = OCMClassMock([SDLPermissionManager class]); __block id streamingManagerMock = OCMClassMock([SDLStreamingMediaManager class]); __block id systemCapabilityMock = OCMClassMock([SDLSystemCapabilityManager class]); - + __block id secondaryTransportManagerMock = OCMClassMock([SDLSecondaryTransportManager class]); + void (^transitionToState)(SDLState *) = ^(SDLState *state) { dispatch_sync(testManager.lifecycleQueue, ^{ [testManager.lifecycleStateMachine transitionToState:state]; @@ -103,9 +120,6 @@ describe(@"a lifecycle manager", ^{ }; beforeEach(^{ - OCMStub([proxyMock iapProxyWithListener:[OCMArg any] secondaryTransportManager:[OCMArg any] encryptionLifecycleManager:[OCMArg any]]).andReturn(proxyMock); - OCMStub([(SDLProxy*)proxyMock protocol]).andReturn(protocolMock); - SDLLifecycleConfiguration *testLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"Test App" appId:@"Test Id"]; testLifecycleConfig.shortAppName = @"Short Name"; testLifecycleConfig.appType = SDLAppHMITypeNavigation; @@ -113,12 +127,18 @@ describe(@"a lifecycle manager", ^{ testConfig = [SDLConfiguration configurationWithLifecycle:testLifecycleConfig lockScreen:[SDLLockScreenConfiguration disabledConfiguration] logging:[SDLLogConfiguration defaultConfiguration] streamingMedia:[SDLStreamingMediaConfiguration insecureConfiguration]]; testConfig.lifecycleConfig.languagesSupported = @[SDLLanguageEnUs, SDLLanguageEnGb]; testConfig.lifecycleConfig.language = SDLLanguageEnUs; + testConfig.lifecycleConfig.minimumProtocolVersion = [SDLVersion versionWithMajor:2 minor:0 patch:0]; + testConfig.lifecycleConfig.minimumRPCVersion = [SDLVersion versionWithMajor:2 minor:0 patch:0]; testManager = [[SDLLifecycleManager alloc] initWithConfiguration:testConfig delegate:OCMProtocolMock(@protocol(SDLManagerDelegate))]; testManager.lockScreenManager = lockScreenManagerMock; testManager.fileManager = fileManagerMock; testManager.permissionManager = permissionManagerMock; testManager.streamManager = streamingManagerMock; testManager.systemCapabilityManager = systemCapabilityMock; + testManager.secondaryTransportManager = secondaryTransportManagerMock; + + [SDLGlobals sharedGlobals].protocolVersion = [SDLVersion versionWithMajor:3 minor:0 patch:0]; + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:3 minor:0 patch:0]; }); it(@"should initialize properties", ^{ @@ -129,7 +149,6 @@ describe(@"a lifecycle manager", ^{ expect(testManager.fileManager).toNot(beNil()); expect(testManager.permissionManager).toNot(beNil()); expect(testManager.streamManager).toNot(beNil()); - expect(testManager.proxy).to(beNil()); expect(testManager.registerResponse).to(beNil()); expect(testManager.lockScreenManager).toNot(beNil()); expect(testManager.notificationDispatcher).toNot(beNil()); @@ -139,6 +158,7 @@ describe(@"a lifecycle manager", ^{ expect(testManager.rpcOperationQueue).toNot(beNil()); expect(@([testManager conformsToProtocol:@protocol(SDLConnectionManagerType)])).to(equal(@YES)); expect(testManager.authToken).to(beNil()); + expect(testManager.currentVRLanguage).toNot(beNil()); }); itBehavesLike(@"unable to send an RPC", ^{ return @{ @"manager": testManager }; }); @@ -214,31 +234,27 @@ describe(@"a lifecycle manager", ^{ readyHandlerSuccess = success; readyHandlerError = error; }]; + + testManager.protocolHandler.protocol = protocolMock; }); - it(@"should initialize the proxy property", ^{ - expect(testManager.proxy).toNot(beNil()); + it(@"should initialize enter the started state and start the secondary transport", ^{ expect(testManager.lifecycleState).to(match(SDLLifecycleStateStarted)); - }); - it(@"should initialize secondary transport manager if not in tcpDebugMode", ^{ - if (!testManager.configuration.lifecycleConfig.tcpDebugMode) { - expect(testManager.secondaryTransportManager).toNot(beNil()); - } + expect(testManager.secondaryTransportManager).toNot(beNil()); }); describe(@"after receiving a connect notification", ^{ beforeEach(^{ // When we connect, we should be creating an sending an RAI - OCMExpect([proxyMock sendRPC:[OCMArg isKindOfClass:[SDLRegisterAppInterface class]]]); + OCMExpect([protocolMock sendRPC:[OCMArg isKindOfClass:[SDLRegisterAppInterface class]]]); - [testManager.notificationDispatcher postNotificationName:SDLTransportDidConnect infoObject:nil]; - [NSThread sleepForTimeInterval:0.1]; + [testManager.notificationDispatcher postNotificationName:SDLRPCServiceDidConnect infoObject:nil]; }); it(@"should send a register app interface request and be in the connected state", ^{ - OCMVerifyAllWithDelay(proxyMock, 0.5); - expect(testManager.lifecycleState).to(match(SDLLifecycleStateConnected)); + OCMVerifyAllWithDelay(protocolMock, 1.0); + expect(testManager.lifecycleState).toEventually(equal(SDLLifecycleStateConnected)); }); itBehavesLike(@"unable to send an RPC", ^{ return @{ @"manager": testManager }; }); @@ -250,7 +266,7 @@ describe(@"a lifecycle manager", ^{ }); it(@"should be in the started state", ^{ - expect(testManager.lifecycleState).to(match(SDLLifecycleStateReconnecting)); + expect(testManager.lifecycleState).to(equal(SDLLifecycleStateReconnecting)); }); }); @@ -258,16 +274,15 @@ describe(@"a lifecycle manager", ^{ it(@"should simply stop", ^{ [testManager stop]; - expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateStopped)); + expect(testManager.lifecycleState).toEventually(equal(SDLLifecycleStateStopped)); }); }); }); describe(@"in the connected state when the minimum protocol version is in effect", ^{ beforeEach(^{ - SDLVersion *oldVersion = [SDLVersion versionWithMajor:0 minor:0 patch:0]; - id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]); - OCMStub([globalMock protocolVersion]).andReturn(oldVersion); + [SDLGlobals sharedGlobals].protocolVersion = [SDLVersion versionWithMajor:1 minor:0 patch:0]; + OCMExpect([protocolMock endServiceWithType:SDLServiceTypeRPC]); [testManager.lifecycleStateMachine setToState:SDLLifecycleStateConnected fromOldState:nil callEnterTransition:YES]; }); @@ -291,7 +306,7 @@ describe(@"a lifecycle manager", ^{ OCMStub([fileManagerMock startWithCompletionHandler:([OCMArg invokeBlockWithArgs:@(YES), fileManagerStartError, nil])]); OCMStub([permissionManagerMock startWithCompletionHandler:([OCMArg invokeBlockWithArgs:@(YES), permissionManagerStartError, nil])]); if (testConfig.lifecycleConfig.tcpDebugMode) { - OCMStub([streamingManagerMock startWithProtocol:protocolMock]); + OCMStub([streamingManagerMock startSecondaryTransportWithProtocol:protocolMock]); } // Send an RAI response & make sure we have an HMI status to move the lifecycle forward @@ -306,7 +321,7 @@ describe(@"a lifecycle manager", ^{ OCMVerify([fileManagerMock startWithCompletionHandler:[OCMArg any]]); OCMVerify([permissionManagerMock startWithCompletionHandler:[OCMArg any]]); if (testManager.configuration.lifecycleConfig.tcpDebugMode) { - OCMVerify([streamingManagerMock startWithProtocol:[OCMArg any]]); + OCMStub([streamingManagerMock startSecondaryTransportWithProtocol:[OCMArg any]]); } }); @@ -315,11 +330,14 @@ describe(@"a lifecycle manager", ^{ describe(@"after receiving a disconnect notification", ^{ beforeEach(^{ + OCMStub([protocolMock stopWithCompletionHandler:[OCMArg invokeBlock]]); + OCMStub([secondaryTransportManagerMock stopWithCompletionHandler:[OCMArg invokeBlock]]); [testManager.notificationDispatcher postNotificationName:SDLTransportDidDisconnect infoObject:nil]; + [NSThread sleepForTimeInterval:1.0]; }); it(@"should enter the started state", ^{ - expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateStarted)); + expect(testManager.lifecycleState).toEventually(equal(SDLLifecycleStateStarted)); }); }); @@ -329,16 +347,14 @@ describe(@"a lifecycle manager", ^{ }); it(@"should enter the stopped state", ^{ - expect(testManager.lifecycleState).to(match(SDLLifecycleStateStopped)); + expect(testManager.lifecycleState).to(equal(SDLLifecycleStateStopped)); }); }); }); describe(@"transitioning to the registered state when the minimum RPC version is in effect", ^{ beforeEach(^{ - SDLVersion *oldVersion = [SDLVersion versionWithMajor:0 minor:0 patch:0]; - id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]); - OCMStub([globalMock rpcVersion]).andReturn(oldVersion); + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:1 minor:0 patch:0]; [testManager.lifecycleStateMachine setToState:SDLLifecycleStateRegistered fromOldState:nil callEnterTransition:YES]; }); @@ -417,57 +433,137 @@ describe(@"a lifecycle manager", ^{ }); context(@"when the register response returns different language than the one passed with the lifecycle configuration", ^{ - beforeEach(^{ - expect(testManager.configuration.lifecycleConfig.appName).to(equal(testConfig.lifecycleConfig.appName)); - expect(testManager.configuration.lifecycleConfig.shortAppName).to(equal(testConfig.lifecycleConfig.shortAppName)); - expect(testManager.configuration.lifecycleConfig.ttsName).to(beNil()); - expect(testManager.configuration.lifecycleConfig.language).to(equal(testConfig.lifecycleConfig.language)); - expect(testManager.configuration.lifecycleConfig.languagesSupported).to(equal(testConfig.lifecycleConfig.languagesSupported)); - }); - - it(@"should should update the configuration when the app supports the head unit language", ^{ - SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; - registerAppInterfaceResponse.success = @YES; - registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; - registerAppInterfaceResponse.info = @"Language mismatch"; - registerAppInterfaceResponse.language = SDLLanguageEnGb; - testManager.registerResponse = registerAppInterfaceResponse; - - SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] initWithAppName:@"EnGb" shortAppName:@"E" ttsName:[SDLTTSChunk textChunksFromString:@"EnGb ttsName"] voiceRecognitionCommandNames:nil]; - OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(update); - - setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); - // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine - [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; - - expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnGb)); - expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"EnGb")); - expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"E")); - expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(equal([SDLTTSChunk textChunksFromString:@"EnGb ttsName"])); - - OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]); + context(@"using the deprecated delegate method", ^{ + __block TestOldConfigurationUpdateManagerDelegate *oldDelegate = nil; + beforeEach(^{ + oldDelegate = OCMClassMock([TestOldConfigurationUpdateManagerDelegate class]); + testManager.delegate = oldDelegate; + }); + + it(@"should should update the configuration when the app supports the head unit language", ^{ + SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; + registerAppInterfaceResponse.success = @YES; + registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; + registerAppInterfaceResponse.info = @"Language mismatch"; + registerAppInterfaceResponse.language = SDLLanguageEnGb; + registerAppInterfaceResponse.hmiDisplayLanguage = SDLLanguageEnGb; + testManager.registerResponse = registerAppInterfaceResponse; + + SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] initWithAppName:@"EnGb" shortAppName:@"E" ttsName:[SDLTTSChunk textChunksFromString:@"EnGb ttsName"] voiceRecognitionCommandNames:nil]; + OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(update); + + setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); + // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; + + expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnGb)); + expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"EnGb")); + expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"E")); + expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(equal([SDLTTSChunk textChunksFromString:@"EnGb ttsName"])); + + OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]); + }); + + it(@"should not update the configuration when the app does not support the head unit language", ^{ + SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; + registerAppInterfaceResponse.success = @YES; + registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; + registerAppInterfaceResponse.info = @"Language mismatch"; + registerAppInterfaceResponse.language = SDLLanguageDeDe; + registerAppInterfaceResponse.hmiDisplayLanguage = SDLLanguageDeDe; + testManager.registerResponse = registerAppInterfaceResponse; + + OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(nil); + + setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); + // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; + + expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnUs)); + expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"Test App")); + expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"Short Name")); + expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(beNil()); + + OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]); + }); }); - it(@"should not update the configuration when the app does not support the head unit language", ^{ - SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; - registerAppInterfaceResponse.success = @YES; - registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; - registerAppInterfaceResponse.info = @"Language mismatch"; - registerAppInterfaceResponse.language = SDLLanguageDeDe; - testManager.registerResponse = registerAppInterfaceResponse; + context(@"using the updated delegate method", ^{ + __block TestNewConfigurationUpdateManagerDelegate *newDelegate = nil; + beforeEach(^{ + newDelegate = OCMClassMock([TestNewConfigurationUpdateManagerDelegate class]); + testManager.delegate = newDelegate; + }); + + it(@"should should update the configuration when the app supports the head unit language", ^{ + SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; + registerAppInterfaceResponse.success = @YES; + registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; + registerAppInterfaceResponse.info = @"Language mismatch"; + registerAppInterfaceResponse.language = SDLLanguageEnGb; + registerAppInterfaceResponse.hmiDisplayLanguage = SDLLanguageEnGb; + testManager.registerResponse = registerAppInterfaceResponse; + + SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] initWithAppName:@"EnGb" shortAppName:@"E" ttsName:[SDLTTSChunk textChunksFromString:@"EnGb ttsName"] voiceRecognitionCommandNames:nil]; + OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any] hmiLanguage:[OCMArg any]]).andReturn(update); - OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]).andReturn(nil); + setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); + // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; - setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); - // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine - [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; + expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnGb)); + expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"EnGb")); + expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"E")); + expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(equal([SDLTTSChunk textChunksFromString:@"EnGb ttsName"])); - expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnUs)); - expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"Test App")); - expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"Short Name")); - expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(beNil()); + OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any] hmiLanguage:[OCMArg any]]); + }); + + it(@"should not update the configuration when the app does not support the head unit language", ^{ + SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; + registerAppInterfaceResponse.success = @YES; + registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; + registerAppInterfaceResponse.info = @"Language mismatch"; + registerAppInterfaceResponse.language = SDLLanguageDeDe; + registerAppInterfaceResponse.hmiDisplayLanguage = SDLLanguageDeDe; + testManager.registerResponse = registerAppInterfaceResponse; + + OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any] hmiLanguage:[OCMArg any]]).andReturn(nil); + + setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); + // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; + + expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnUs)); + expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"Test App")); + expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"Short Name")); + expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(beNil()); + + OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any] hmiLanguage:[OCMArg any]]); + }); + + it(@"should update if the hmi display language changes", ^{ + SDLRegisterAppInterfaceResponse *registerAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init]; + registerAppInterfaceResponse.success = @YES; + registerAppInterfaceResponse.resultCode = SDLResultWrongLanguage; + registerAppInterfaceResponse.info = @"Language mismatch"; + registerAppInterfaceResponse.language = SDLLanguageEnUs; + registerAppInterfaceResponse.hmiDisplayLanguage = SDLLanguageEnGb; + testManager.registerResponse = registerAppInterfaceResponse; + + OCMStub([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any] hmiLanguage:[OCMArg any]]).andReturn(nil); - OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any]]); + setToStateWithEnterTransition(SDLLifecycleStateRegistered, SDLLifecycleStateUpdatingConfiguration); + // Transition to StateSettingUpManagers to prevent assert error from the lifecycle machine + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateSettingUpManagers fromOldState:SDLLifecycleStateUpdatingConfiguration callEnterTransition:NO]; + + expect(testManager.configuration.lifecycleConfig.language).toEventually(equal(SDLLanguageEnUs)); + expect(testManager.configuration.lifecycleConfig.appName).toEventually(equal(@"Test App")); + expect(testManager.configuration.lifecycleConfig.shortAppName).toEventually(equal(@"Short Name")); + expect(testManager.configuration.lifecycleConfig.ttsName).toEventually(beNil()); + + OCMVerify([testManager.delegate managerShouldUpdateLifecycleToLanguage:[OCMArg any] hmiLanguage:[OCMArg any]]); + }); }); }); }); @@ -479,33 +575,30 @@ describe(@"a lifecycle manager", ^{ it(@"can send an RPC of type Request", ^{ SDLShow *testShow = [[SDLShow alloc] initWithMainField1:@"test" mainField2:nil alignment:nil]; + OCMExpect([protocolMock sendRPC:testShow]); [testManager sendRPC:testShow]; - [NSThread sleepForTimeInterval:0.1]; - - OCMVerify([proxyMock sendRPC:[OCMArg isKindOfClass:SDLShow.class]]); + OCMVerifyAllWithDelay(protocolMock, 0.1); }); it(@"can send an RPC of type Response", ^{ SDLPerformAppServiceInteractionResponse *testResponse = [[SDLPerformAppServiceInteractionResponse alloc] init]; + OCMExpect([protocolMock sendRPC:testResponse]); [testManager sendRPC:testResponse]; testResponse.correlationID = @(2); testResponse.success = @(true); testResponse.resultCode = SDLResultSuccess; testResponse.info = @"testResponse info"; - [NSThread sleepForTimeInterval:0.1]; - - OCMVerify([proxyMock sendRPC:[OCMArg isKindOfClass:SDLPerformAppServiceInteractionResponse.class]]); + OCMVerifyAllWithDelay(protocolMock, 0.1); }); it(@"can send an RPC of type Notification", ^{ SDLOnAppServiceData *testNotification = [[SDLOnAppServiceData alloc] initWithServiceData:[[SDLAppServiceData alloc] init]]; + OCMExpect([protocolMock sendRPC:testNotification]); [testManager sendRPC:testNotification]; - [NSThread sleepForTimeInterval:0.1]; - - OCMVerify([proxyMock sendRPC:[OCMArg isKindOfClass:SDLOnAppServiceData.class]]); + OCMVerifyAllWithDelay(protocolMock, 0.1); }); it(@"should throw an exception if the RPC is not of type `Request`, `Response` or `Notification`", ^{ @@ -546,7 +639,7 @@ describe(@"a lifecycle manager", ^{ }); it(@"should attempt to unregister", ^{ - OCMVerify([proxyMock sendRPC:[OCMArg isKindOfClass:[SDLUnregisterAppInterface class]]]); + OCMVerify([protocolMock sendRPC:[OCMArg isKindOfClass:[SDLUnregisterAppInterface class]]]); expect(testManager.lifecycleState).toEventually(match(SDLLifecycleStateUnregistering)); }); @@ -698,26 +791,56 @@ describe(@"a lifecycle manager", ^{ }); }); }); -}); - -describe(@"configuring the lifecycle manager", ^{ - __block SDLLifecycleConfiguration *lifecycleConfig = nil; - __block SDLLifecycleManager *testManager = nil; - beforeEach(^{ - lifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"Test app" fullAppId:@"Test ID"]; - }); + describe(@"configuring the lifecycle manager", ^{ + __block SDLLifecycleConfiguration *lifecycleConfig = nil; + __block SDLLifecycleManager *testManager = nil; - context(@"if no secondary transport is allowed", ^{ beforeEach(^{ - lifecycleConfig.allowedSecondaryTransports = SDLSecondaryTransportsNone; + lifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"Test app" fullAppId:@"Test ID"]; + }); + + context(@"if secondary transport is not allowed", ^{ + beforeEach(^{ + lifecycleConfig.allowedSecondaryTransports = SDLSecondaryTransportsNone; + SDLConfiguration *config = [[SDLConfiguration alloc] initWithLifecycle:lifecycleConfig lockScreen:nil logging:nil fileManager:nil]; + testManager = [[SDLLifecycleManager alloc] initWithConfiguration:config delegate:nil]; + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateStarted fromOldState:nil callEnterTransition:YES]; + }); + + it(@"should not create a secondary transport manager", ^{ + expect(testManager.secondaryTransportManager).to(beNil()); + }); + }); - SDLConfiguration *config = [[SDLConfiguration alloc] initWithLifecycle:lifecycleConfig lockScreen:nil logging:nil fileManager:nil]; - testManager = [[SDLLifecycleManager alloc] initWithConfiguration:config delegate:nil]; + context(@"if a secondary transport is allowed but app is NOT a navigation or projection app", ^{ + beforeEach(^{ + lifecycleConfig.allowedSecondaryTransports = SDLSecondaryTransportsTCP; + lifecycleConfig.appType = SDLAppHMITypeSocial; + SDLConfiguration *config = [[SDLConfiguration alloc] initWithLifecycle:lifecycleConfig lockScreen:nil logging:nil fileManager:nil]; + testManager = [[SDLLifecycleManager alloc] initWithConfiguration:config delegate:nil]; + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateStarted fromOldState:nil callEnterTransition:YES]; + }); + + it(@"should not create a secondary transport manager", ^{ + expect(testManager.secondaryTransportManager).to(beNil()); + }); }); - it(@"should not create a secondary transport manager", ^{ - expect(testManager.secondaryTransportManager).to(beNil()); + context(@"if a secondary transport is allowed and app is a navigation or projection app", ^{ + beforeEach(^{ + lifecycleConfig.allowedSecondaryTransports = SDLSecondaryTransportsTCP; + lifecycleConfig.appType = SDLAppHMITypeProjection; + SDLConfiguration *config = [[SDLConfiguration alloc] initWithLifecycle:lifecycleConfig lockScreen:nil logging:nil streamingMedia:SDLStreamingMediaConfiguration.insecureConfiguration fileManager:nil]; + testManager = [[SDLLifecycleManager alloc] initWithConfiguration:config delegate:nil]; + + [testManager.lifecycleStateMachine setToState:SDLLifecycleStateStarted fromOldState:nil callEnterTransition:YES]; + }); + + it(@"should create a secondary transport manager", ^{ + expect(testManager.streamManager).toNot(beNil()); + expect(testManager.secondaryTransportManager).toNot(beNil()); + }); }); }); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleMobileHMIStateHandlerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleMobileHMIStateHandlerSpec.m new file mode 100644 index 000000000..f2ff80c99 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleMobileHMIStateHandlerSpec.m @@ -0,0 +1,88 @@ +// +// SDLLifecycleMobileHMIStateHandler.m +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/24/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> + +#import "SDLLifecycleMobileHMIStateHandler.h" +#import "SDLNotificationConstants.h" +#import "SDLRegisterAppInterfaceResponse.h" +#import "SDLRPCResponseNotification.h" +#import "SDLMsgVersion.h" + +#import "TestConnectionManager.h" + +QuickSpecBegin(SDLLifecycleMobileHMIStateHandlerSpec) + +describe(@"SDLLifecycleMobileHMIStateHandler tests", ^{ + __block TestConnectionManager *mockConnectionManager = nil; + __block SDLLifecycleMobileHMIStateHandler *testManager = nil; + + beforeEach(^{ + mockConnectionManager = [[TestConnectionManager alloc] init]; + testManager = [[SDLLifecycleMobileHMIStateHandler alloc] initWithConnectionManager:mockConnectionManager]; + }); + + context(@"before a RAIR", ^{ + it(@"should do nothing if the app changes foreground states", ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil]; + + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + + context(@"after a RAIR", ^{ + context(@"with msg version < 4", ^{ + beforeEach(^{ + SDLRegisterAppInterfaceResponse *rair = [[SDLRegisterAppInterfaceResponse alloc] init]; + rair.sdlMsgVersion = [[SDLMsgVersion alloc] initWithMajorVersion:3 minorVersion:0 patchVersion:0]; + + SDLRPCResponseNotification *responseNotification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:nil rpcResponse:rair]; + [[NSNotificationCenter defaultCenter] postNotification:responseNotification]; + }); + + it(@"should do nothing if the app changes foreground states", ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil]; + + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + + context(@"with msg version >= 4", ^{ + beforeEach(^{ + SDLRegisterAppInterfaceResponse *rair = [[SDLRegisterAppInterfaceResponse alloc] init]; + rair.sdlMsgVersion = [[SDLMsgVersion alloc] initWithMajorVersion:5 minorVersion:0 patchVersion:0]; + + SDLRPCResponseNotification *responseNotification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:nil rpcResponse:rair]; + [[NSNotificationCenter defaultCenter] postNotification:responseNotification]; + }); + + it(@"should send an OnHMIStatus as well as another if the app changes foreground states", ^{ + expect(mockConnectionManager.receivedRequests).to(haveCount(1)); + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil]; + expect(mockConnectionManager.receivedRequests).to(haveCount(2)); + }); + + describe(@"after the manager is stopped", ^{ + beforeEach(^{ + [mockConnectionManager.receivedRequests removeAllObjects]; + [testManager stop]; + }); + + it(@"should do nothing if the app changes foreground states", ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil]; + + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleProtocolHandlerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleProtocolHandlerSpec.m new file mode 100644 index 000000000..681ec9cc5 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleProtocolHandlerSpec.m @@ -0,0 +1,233 @@ +// +// SDLLifecycleProtocolHandler.m +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/25/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> +#import <OCMock/OCMock.h> + +#import "SDLConfiguration.h" +#import "SDLFunctionID.h" +#import "SDLLifecycleConfiguration.h" +#import "SDLLifecycleProtocolHandler.h" +#import "SDLNotificationConstants.h" +#import "SDLNotificationDispatcher.h" +#import "SDLProtocol.h" +#import "SDLProtocolDelegate.h" +#import "SDLProtocolHeader.h" +#import "SDLProtocolMessage.h" +#import "SDLRPCPayload.h" +#import "SDLShow.h" +#import "SDLTimer.h" + +@interface SDLLifecycleProtocolHandler () + +@property (weak, nonatomic) SDLNotificationDispatcher *notificationDispatcher; +@property (strong, nonatomic) SDLTimer *rpcStartServiceTimeoutTimer; +@property (copy, nonatomic) NSString *appId; + +@end + +QuickSpecBegin(SDLLifecycleProtocolHandlerSpec) + +describe(@"SDLLifecycleProtocolHandler tests", ^{ + __block SDLLifecycleProtocolHandler *testHandler = nil; + __block id mockProtocol = nil; + __block id mockNotificationDispatcher = nil; + __block id mockTimer = nil; + + beforeEach(^{ + mockProtocol = OCMClassMock([SDLProtocol class]); + mockNotificationDispatcher = OCMClassMock([SDLNotificationDispatcher class]); + mockTimer = OCMClassMock([SDLTimer class]); + + SDLLifecycleConfiguration *testLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"test" fullAppId:@"appid"]; + SDLConfiguration *testConfig = [[SDLConfiguration alloc] initWithLifecycle:testLifecycleConfig lockScreen:nil logging:nil fileManager:nil encryption:nil]; + + testHandler = [[SDLLifecycleProtocolHandler alloc] initWithProtocol:mockProtocol notificationDispatcher:mockNotificationDispatcher configuration:testConfig]; + testHandler.rpcStartServiceTimeoutTimer = mockTimer; + }); + + describe(@"when started", ^{ + beforeEach(^{ + OCMExpect([(SDLProtocol *)mockProtocol start]); + [testHandler start]; + }); + + it(@"should start the protocol", ^{ + OCMVerifyAll(mockProtocol); + }); + }); + + describe(@"when stopped", ^{ + beforeEach(^{ + OCMExpect([(SDLProtocol *)mockProtocol stopWithCompletionHandler:[OCMArg any]]); + [testHandler stopWithCompletionHandler:^{}]; + }); + + it(@"should stop the protocol", ^{ + OCMVerifyAll(mockProtocol); + }); + }); + + describe(@"when the protocol notifies us", ^{ + context(@"of the transport opening", ^{ + beforeEach(^{ + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLTransportDidConnect] infoObject:[OCMArg isNil]]); + OCMExpect([mockProtocol startServiceWithType:0 payload:[OCMArg any]]).ignoringNonObjectArgs(); + OCMExpect([(SDLTimer *)mockTimer start]); + [testHandler protocolDidOpen:mockProtocol]; + }); + + it(@"should set everything up", ^{ + OCMVerifyAll(mockNotificationDispatcher); + OCMVerifyAll(mockProtocol); + OCMVerifyAll(mockTimer); + }); + }); + + context(@"of the transport closing", ^{ + beforeEach(^{ + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLTransportDidDisconnect] infoObject:[OCMArg isNil]]); + [testHandler protocolDidClose:mockProtocol]; + }); + + it(@"should send a notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + }); + }); + + context(@"of the transport erroring", ^{ + beforeEach(^{ + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLTransportConnectError] infoObject:[OCMArg isNotNil]]); + [testHandler protocol:mockProtocol transportDidError:[NSError errorWithDomain:@"test" code:1 userInfo:nil]]; + }); + + it(@"should send a notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + }); + }); + + context(@"of an RPC Start Service ACK", ^{ + beforeEach(^{ + SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:4]; + header.serviceType = SDLServiceTypeRPC; + header.frameData = SDLFrameInfoStartServiceACK; + SDLProtocolMessage *message = [SDLProtocolMessage messageWithHeader:header andPayload:nil]; + + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLRPCServiceDidConnect] infoObject:[OCMArg isNil]]); + OCMExpect([(SDLTimer *)mockTimer cancel]); + + [testHandler protocol:mockProtocol didReceiveStartServiceACK:message]; + }); + + it(@"should stop the timer and send a notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + OCMVerifyAll(mockTimer); + }); + }); + + context(@"of an RPC Start Service NAK", ^{ + beforeEach(^{ + SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:4]; + header.serviceType = SDLServiceTypeRPC; + header.frameData = SDLFrameInfoStartServiceNACK; + SDLProtocolMessage *message = [SDLProtocolMessage messageWithHeader:header andPayload:nil]; + + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLRPCServiceConnectionDidError] infoObject:[OCMArg isNil]]); + OCMExpect([(SDLTimer *)mockTimer cancel]); + + [testHandler protocol:mockProtocol didReceiveStartServiceNAK:message]; + }); + + it(@"should stop the timer and send a notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + OCMVerifyAll(mockTimer); + }); + }); + + context(@"no response from the module to the RPC Start Service", ^{ + beforeEach(^{ + testHandler.rpcStartServiceTimeoutTimer = nil; + }); + + it(@"should send a transport disconnected notification when the timer elapses", ^{ + OCMExpect([mockProtocol stopWithCompletionHandler:[OCMArg any]]); + + [testHandler protocolDidOpen:mockProtocol]; + + OCMVerifyAllWithDelay(mockProtocol, 11.0); + }); + }); + + context(@"of an RPC End Service ACK", ^{ + beforeEach(^{ + SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:4]; + header.serviceType = SDLServiceTypeRPC; + header.frameData = SDLFrameInfoEndServiceACK; + SDLProtocolMessage *message = [SDLProtocolMessage messageWithHeader:header andPayload:nil]; + + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLRPCServiceDidDisconnect] infoObject:[OCMArg isNil]]); + OCMExpect([(SDLTimer *)mockTimer cancel]); + + [testHandler protocol:mockProtocol didReceiveEndServiceACK:message]; + }); + + it(@"should stop the timer and send a notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + OCMVerifyAll(mockTimer); + }); + }); + + context(@"of an RPC End Service NAK", ^{ + beforeEach(^{ + SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:4]; + header.serviceType = SDLServiceTypeRPC; + header.frameData = SDLFrameInfoEndServiceNACK; + SDLProtocolMessage *message = [SDLProtocolMessage messageWithHeader:header andPayload:nil]; + + OCMExpect([mockNotificationDispatcher postNotificationName:[OCMArg isEqual:SDLRPCServiceConnectionDidError] infoObject:[OCMArg any]]); + + [testHandler protocol:mockProtocol didReceiveEndServiceNAK:message]; + }); + + it(@"should send a RPC service connection error notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + }); + }); + + context(@"of a protocol message", ^{ + beforeEach(^{ + SDLShow *showRPC = [[SDLShow alloc] initWithMainField1:@"Test1" mainField2:@"Test2" alignment:SDLTextAlignmentLeft]; + + SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:4]; + header.serviceType = SDLServiceTypeRPC; + header.frameData = SDLFrameInfoSingleFrame; + + NSDictionary *dict = [showRPC serializeAsDictionary:4]; + NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:nil]; + SDLRPCPayload *messagePayload = [[SDLRPCPayload alloc] init]; + messagePayload.jsonData = data; + messagePayload.rpcType = SDLRPCMessageTypeRequest; + messagePayload.correlationID = 1; + messagePayload.functionID = [[SDLFunctionID sharedInstance] functionIdForName:SDLRPCFunctionNameShow].unsignedIntValue; + + SDLProtocolMessage *testMessage = [SDLProtocolMessage messageWithHeader:header andPayload:messagePayload.data]; + + OCMExpect([mockNotificationDispatcher postRPCRequestNotification:[OCMArg isEqual:SDLDidReceiveShowRequest] request:[OCMArg isNotNil]]); + + [testHandler protocol:mockProtocol didReceiveMessage:testMessage]; + }); + + it(@"should send the notification", ^{ + OCMVerifyAll(mockNotificationDispatcher); + }); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleRPCAdapterSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleRPCAdapterSpec.m new file mode 100644 index 000000000..e589c2a71 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleRPCAdapterSpec.m @@ -0,0 +1,306 @@ +// +// SDLLifecycleRPCAdapterSpec.m +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/23/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> + +#import "SDLGlobals.h" +#import "SDLLifecycleRPCAdapter.h" +#import "SDLOnButtonEvent.h" +#import "SDLOnButtonPress.h" +#import "SDLShow.h" +#import "SDLSubscribeButton.h" +#import "SDLUnsubscribeButton.h" +#import "SDLVersion.h" + +QuickSpecBegin(SDLLifecycleRPCAdapterSpec) + +describe(@"the lifecycle RPC adapter", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:1 minor:0 patch:0]; + }); + + describe(@"adapt subscribe button request", ^{ + __block SDLSubscribeButton *testRPC = nil; + beforeEach(^{ + testRPC = [[SDLSubscribeButton alloc] init]; + + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:1 minor:0 patch:0]; + }); + + context(@"before RPC v5.0", ^{ + context(@"if the button name is PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should change it to an OK message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(1)); + expect(((SDLSubscribeButton *)result[0]).buttonName).to(equal(SDLButtonNameOk)); + }); + }); + + context(@"if the button name is not PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should not do anything to the message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(1)); + }); + }); + }); + + context(@"after or equal to RPC v5.0", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:5 minor:0 patch:0]; + }); + + context(@"if the button name is OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should create an additional PlayPause message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(2)); + expect(((SDLSubscribeButton *)result[1]).buttonName).to(equal(SDLButtonNamePlayPause)); + }); + }); + + context(@"if the button name is not OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should not do anything to the message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(1)); + }); + }); + }); + }); + + describe(@"adapt unsubscribe button request", ^{ + __block SDLUnsubscribeButton *testRPC = nil; + beforeEach(^{ + testRPC = [[SDLUnsubscribeButton alloc] init]; + }); + + context(@"before RPC v5.0", ^{ + context(@"if the button name is PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should change it to an OK message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(1)); + expect(((SDLUnsubscribeButton *)result[0]).buttonName).to(equal(SDLButtonNameOk)); + }); + }); + + context(@"if the button name is not PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should not do anything to the message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(1)); + }); + }); + }); + + context(@"after or equal to RPC v5.0", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:5 minor:0 patch:0]; + }); + + context(@"if the button name is OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should create an additional PlayPause message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(2)); + expect(((SDLUnsubscribeButton *)result[1]).buttonName).to(equal(SDLButtonNamePlayPause)); + }); + }); + + context(@"if the button name is not OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should not do anything to the message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionOutgoing]; + + expect(result).to(haveCount(1)); + }); + }); + }); + }); + + describe(@"adapt onButtonPress notification", ^{ + __block SDLOnButtonPress *testRPC = nil; + beforeEach(^{ + testRPC = [[SDLOnButtonPress alloc] init]; + }); + + context(@"before RPC v5.0", ^{ + context(@"if the button name is PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should drop the message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(beEmpty()); + }); + }); + + context(@"if the button name is OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should create an additional play-pause message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(2)); + expect(((SDLOnButtonPress *)result[1]).buttonName).to(equal(SDLButtonNamePlayPause)); + }); + }); + }); + + context(@"after or equal to RPC v5.0", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:5 minor:0 patch:0]; + }); + + context(@"if the button name is OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should create an additional PlayPause message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(2)); + expect(((SDLOnButtonPress *)result[1]).buttonName).to(equal(SDLButtonNamePlayPause)); + }); + }); + + context(@"if the button name is PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should create an additional OK message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(2)); + expect(((SDLOnButtonPress *)result[1]).buttonName).to(equal(SDLButtonNameOk)); + }); + }); + }); + }); + + describe(@"adapt onButtonEvent notification", ^{ + __block SDLOnButtonEvent *testRPC = nil; + beforeEach(^{ + testRPC = [[SDLOnButtonEvent alloc] init]; + }); + + context(@"before RPC v5.0", ^{ + context(@"if the button name is PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should drop the message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(beEmpty()); + }); + }); + + context(@"if the button name is OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should create an additional play-pause message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(2)); + expect(((SDLOnButtonEvent *)result[1]).buttonName).to(equal(SDLButtonNamePlayPause)); + }); + }); + }); + + context(@"after or equal to RPC v5.0", ^{ + beforeEach(^{ + [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:5 minor:0 patch:0]; + }); + + context(@"if the button name is OK", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNameOk; + }); + + it(@"should create an additional PlayPause message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(2)); + expect(((SDLOnButtonEvent *)result[1]).buttonName).to(equal(SDLButtonNamePlayPause)); + }); + }); + + context(@"if the button name is PlayPause", ^{ + beforeEach(^{ + testRPC.buttonName = SDLButtonNamePlayPause; + }); + + it(@"should create an additional OK message", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(2)); + expect(((SDLOnButtonEvent *)result[1]).buttonName).to(equal(SDLButtonNameOk)); + }); + }); + }); + }); + + describe(@"an RPC that is not handled", ^{ + __block SDLShow *testRPC = nil; + beforeEach(^{ + testRPC = [[SDLShow alloc] init]; + }); + + it(@"should not do anything to the RPC", ^{ + NSArray<SDLRPCMessage *> *result = [SDLLifecycleRPCAdapter adaptRPC:testRPC direction:SDLRPCDirectionIncoming]; + + expect(result).to(haveCount(1)); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSyncPDataHandlerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSyncPDataHandlerSpec.m new file mode 100644 index 000000000..9c38944b2 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSyncPDataHandlerSpec.m @@ -0,0 +1,78 @@ +// +// SDLLifecycleSyncPDataHandler.m +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/24/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> +#import <OCMock/OCMock.h> + +#import "SDLEncodedSyncPData.h" +#import "SDLLifecycleSyncPDataHandler.h" +#import "SDLNotificationConstants.h" +#import "SDLOnEncodedSyncPData.h" +#import "SDLRPCNotificationNotification.h" + +#import "TestConnectionManager.h" + +@interface SDLLifecycleSyncPDataHandler () + +@property (strong, nonatomic) NSURLSession *urlSession; + +@end + +QuickSpecBegin(SDLLifecycleSyncPDataHandlerSpec) + +describe(@"Test SDLLifecycleSyncPDataHandler", ^{ + __block SDLLifecycleSyncPDataHandler *testHandler = nil; + __block TestConnectionManager *mockConnectionManager = nil; + __block NSURLSession *mockSession = nil; + + beforeEach(^{ + mockSession = OCMClassMock([NSURLSession class]); + + NSData *receivedData = [NSJSONSerialization dataWithJSONObject:@{@"data": @[@"1234"]} options:kNilOptions error:nil]; + OCMStub([mockSession uploadTaskWithRequest:[OCMArg any] fromData:[OCMArg any] completionHandler:([OCMArg invokeBlockWithArgs:receivedData, [[NSURLResponse alloc] init], [NSNull null], nil])]); + + mockConnectionManager = [[TestConnectionManager alloc] init]; + testHandler = [[SDLLifecycleSyncPDataHandler alloc] initWithConnectionManager:mockConnectionManager]; + testHandler.urlSession = mockSession; + }); + + describe(@"when a OnEncodedSyncPData request comes in", ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + __block SDLOnEncodedSyncPData *testRPC = nil; +#pragma clang diagnostic pop + beforeEach(^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + testRPC = [[SDLOnEncodedSyncPData alloc] init]; +#pragma clang diagnostic pop + testRPC.URL = @"https://www.google.com"; + testRPC.Timeout = @(30); + testRPC.data = @[@"1234/5678"]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveEncodedDataNotification object:nil rpcNotification:testRPC]; +#pragma clang diagnostic pop + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should send a EncodedSyncPData request", ^{ + expect(mockConnectionManager.receivedRequests).to(haveCount(1)); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + SDLEncodedSyncPData *sentRequest = mockConnectionManager.receivedRequests[0]; +#pragma clang diagnostic pop + expect(sentRequest.data).to(equal(@[@"1234"])); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m new file mode 100644 index 000000000..01211e324 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleSystemRequestHandlerSpec.m @@ -0,0 +1,235 @@ +// +// SDLLifecycleSystemRequestHandlerSpec.m +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/24/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> +#import <OCMock/OCMock.h> + +#import "SDLCacheFileManager.h" +#import "SDLFileType.h" +#import "SDLLifecycleSystemRequestHandler.h" +#import "SDLNotificationConstants.h" +#import "SDLOnSystemRequest.h" +#import "SDLPutFile.h" +#import "SDLRequestType.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLSystemRequest.h" + +#import "TestConnectionManager.h" + +@interface SDLLifecycleSystemRequestHandler () + +@property (strong, nonatomic) SDLCacheFileManager *cacheFileManager; +@property (strong, nonatomic) NSURLSession *urlSession; + +@end + +QuickSpecBegin(SDLLifecycleSystemRequestHandlerSpec) + +describe(@"SDLLifecycleSystemRequestHandler tests", ^{ + __block TestConnectionManager *mockConnectionManager = nil; + __block SDLLifecycleSystemRequestHandler *testManager = nil; + __block id mockSession = nil; + __block id mockCacheManager = nil; + + beforeEach(^{ + mockCacheManager = OCMClassMock([SDLCacheFileManager class]); + mockSession = OCMClassMock([NSURLSession class]); + + mockConnectionManager = [[TestConnectionManager alloc] init]; + + testManager = [[SDLLifecycleSystemRequestHandler alloc] initWithConnectionManager:mockConnectionManager]; + testManager.urlSession = mockSession; + testManager.cacheFileManager = mockCacheManager; + }); + + describe(@"when receiving an OnSystemRequest", ^{ + __block SDLOnSystemRequest *receivedSystemRequest = nil; + beforeEach(^{ + receivedSystemRequest = [[SDLOnSystemRequest alloc] init]; + }); + + context(@"of type PROPRIETARY", ^{ + __block NSData *urlReceivedData = nil; + + beforeEach(^{ + receivedSystemRequest.requestType = SDLRequestTypeProprietary; + receivedSystemRequest.url = @"https://www.google.com"; + receivedSystemRequest.fileType = SDLFileTypeJSON; + + urlReceivedData = [@"5678" dataUsingEncoding:NSASCIIStringEncoding]; + receivedSystemRequest.bulkData = [NSJSONSerialization dataWithJSONObject:@{@"data": @"1234"} options:kNilOptions error:nil]; + + OCMStub([mockSession uploadTaskWithRequest:[OCMArg any] fromData:[OCMArg any] completionHandler:([OCMArg invokeBlockWithArgs:urlReceivedData, [[NSURLResponse alloc] init], [NSNull null], nil])]).andReturn(nil); + }); + + context(@"when the file type is not JSON", ^{ + beforeEach(^{ + receivedSystemRequest.fileType = SDLFileTypeBMP; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should not send a SystemRequest", ^{ + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + + context(@"when the url is nil", ^{ + beforeEach(^{ + receivedSystemRequest.url = nil; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should not send a SystemRequest", ^{ + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + + context(@"when the bulkdata is not JSON", ^{ + beforeEach(^{ + receivedSystemRequest.bulkData = [@"1234" dataUsingEncoding:NSASCIIStringEncoding]; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should not send a SystemRequest", ^{ + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + + context(@"when formed correctly", ^{ + beforeEach(^{ + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should send a SystemRequest", ^{ + expect(mockConnectionManager.receivedRequests).to(haveCount(1)); + expect(mockConnectionManager.receivedRequests[0]).to(beAnInstanceOf([SDLSystemRequest class])); + expect(((SDLSystemRequest *)mockConnectionManager.receivedRequests[0]).requestType).to(equal(SDLRequestTypeProprietary)); + expect(((SDLSystemRequest *)mockConnectionManager.receivedRequests[0]).bulkData).to(equal([@"5678" dataUsingEncoding:NSASCIIStringEncoding])); + }); + }); + }); + + context(@"of type LOCK_SCREEN_URL", ^{ + __block id lockScreenIconObserver = nil; + + beforeEach(^{ + receivedSystemRequest.requestType = SDLRequestTypeLockScreenIconURL; + + UIImage *testImage = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; + OCMStub([mockCacheManager retrieveImageForRequest:[OCMArg any] withCompletionHandler:([OCMArg invokeBlockWithArgs:testImage, [NSNull null], nil])]); + + lockScreenIconObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:lockScreenIconObserver name:SDLDidReceiveLockScreenIcon object:nil]; + [[lockScreenIconObserver expect] notificationWithName:SDLDidReceiveLockScreenIcon object:[OCMArg any] userInfo:[OCMArg any]]; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should pass the url to the cache manager and then send a notification", ^{ + OCMVerifyAll(lockScreenIconObserver); + }); + + afterEach(^{ + lockScreenIconObserver = nil; + }); + }); + + context(@"of type ICON_URL", ^{ + beforeEach(^{ + receivedSystemRequest.requestType = SDLRequestTypeIconURL; + receivedSystemRequest.url = @"https://www.google.com"; + + NSData *data = [@"1234" dataUsingEncoding:NSASCIIStringEncoding]; + OCMStub([mockSession dataTaskWithURL:[OCMArg any] completionHandler:([OCMArg invokeBlockWithArgs:data, [NSURLResponse new], [NSNull null], nil])]); + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should send a SystemRequest", ^{ + expect(mockConnectionManager.receivedRequests).to(haveCount(1)); + expect(mockConnectionManager.receivedRequests[0]).to(beAnInstanceOf([SDLSystemRequest class])); + }); + }); + + context(@"of type HTTP", ^{ + __block NSData *urlReceivedData = nil; + + beforeEach(^{ + receivedSystemRequest.requestType = SDLRequestTypeHTTP; + receivedSystemRequest.url = @"https://www.google.com"; + receivedSystemRequest.bulkData = [@"1234" dataUsingEncoding:NSASCIIStringEncoding]; + + urlReceivedData = [NSJSONSerialization dataWithJSONObject:@{@"data": @[@"1234"]} options:kNilOptions error:nil]; + OCMStub([mockSession uploadTaskWithRequest:[OCMArg any] fromData:[OCMArg any] completionHandler:([OCMArg invokeBlockWithArgs:urlReceivedData, [[NSURLResponse alloc] init], [NSNull null], nil])]).andReturn(nil); + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should send a PutFile after receiving a response", ^{ + expect(mockConnectionManager.receivedRequests).to(haveCount(1)); + + SDLPutFile *putFile = mockConnectionManager.receivedRequests[0]; + expect(putFile.fileType).to(equal(SDLFileTypeJSON)); + expect(putFile.sdlFileName).to(equal(@"response_data")); + expect(putFile.bulkData).to(equal(urlReceivedData)); + }); + }); + + context(@"of type LAUNCH_APP", ^{ + __block id mockedApplication = nil; + + beforeEach(^{ + receivedSystemRequest.requestType = SDLRequestTypeLaunchApp; + receivedSystemRequest.url = @"myApp://"; + + mockedApplication = OCMClassMock([UIApplication class]); + OCMStub([mockedApplication sharedApplication]).andReturn(mockedApplication); + OCMExpect([mockedApplication openURL:[OCMArg checkWithBlock:^BOOL(id obj) { + return [((NSURL *)obj).absoluteString isEqualToString:@"myApp://"]; + }]]); + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should have attempted to open the URL", ^{ + OCMVerifyAllWithDelay(mockedApplication, 0.5); + }); + + afterEach(^{ + [mockedApplication stopMocking]; + }); + }); + + context(@"of another type", ^{ + beforeEach(^{ + receivedSystemRequest.requestType = SDLRequestTypeFOTA; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemRequestNotification object:nil rpcNotification:receivedSystemRequest]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + }); + + it(@"should do nothing", ^{ + OCMReject([mockSession uploadTaskWithRequest:[OCMArg any] fromData:[OCMArg any] completionHandler:[OCMArg any]]).andReturn(nil); + }); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m index 30949168a..7357b9e9f 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLockScreenManagerSpec.m @@ -6,6 +6,7 @@ #import "SDLLockScreenConfiguration.h" #import "SDLLockScreenManager.h" #import "SDLLockScreenStatus.h" +#import "SDLLockScreenStatusManager.h" #import "SDLLockScreenViewController.h" #import "SDLNotificationConstants.h" #import "SDLNotificationDispatcher.h" @@ -18,6 +19,7 @@ @property (assign, nonatomic) BOOL canPresent; @property (strong, nonatomic, readwrite) SDLLockScreenConfiguration *config; @property (strong, nonatomic) id<SDLViewControllerPresentable> presenter; +@property (strong, nonatomic) SDLLockScreenStatusManager *statusManager; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -34,21 +36,22 @@ QuickSpecBegin(SDLLockScreenManagerSpec) describe(@"a lock screen manager", ^{ __block SDLLockScreenManager *testManager = nil; - __block SDLFakeViewControllerPresenter *fakePresenter = nil; - __block SDLNotificationDispatcher *testNotificationDispatcher = nil; + __block SDLFakeViewControllerPresenter *fakeViewControllerPresenter = nil; + __block SDLNotificationDispatcher *dispatcherMock = nil; beforeEach(^{ - fakePresenter = [[SDLFakeViewControllerPresenter alloc] init]; + fakeViewControllerPresenter = [[SDLFakeViewControllerPresenter alloc] init]; + dispatcherMock = OCMClassMock([SDLNotificationDispatcher class]); }); context(@"with a disabled configuration", ^{ beforeEach(^{ - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration disabledConfiguration] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration disabledConfiguration] notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ // Note: We can't check the "lockScreenPresented" flag on the Lock Screen Manager because it's a computer property checking the window - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -58,7 +61,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should not have a lock screen controller", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -66,21 +69,16 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" __block SDLOnLockScreenStatus *testRequiredStatus = nil; -#pragma clang diagnostic pop beforeEach(^{ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" testRequiredStatus = [[SDLOnLockScreenStatus alloc] init]; -#pragma clang diagnostic pop - testRequiredStatus.lockScreenStatus = SDLLockScreenStatusRequired; - - [testNotificationDispatcher postNotificationName:SDLDidChangeLockScreenStatusNotification infoObject:testRequiredStatus]; + [dispatcherMock postNotificationName:SDLDidChangeLockScreenStatusNotification infoObject:testRequiredStatus]; +#pragma clang diagnostic pop }); it(@"should not have presented the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); }); }); }); @@ -88,11 +86,11 @@ describe(@"a lock screen manager", ^{ context(@"with an enabled configuration", ^{ beforeEach(^{ - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfiguration] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfiguration] notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -102,7 +100,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should set up the view controller correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).toNot(beNil()); expect(testManager.lockScreenViewController).to(beAnInstanceOf([SDLLockScreenViewController class])); }); @@ -118,35 +116,20 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" testRequiredStatus = [[SDLOnLockScreenStatus alloc] init]; -#pragma clang diagnostic pop testRequiredStatus.lockScreenStatus = SDLLockScreenStatusRequired; - - SDLRPCNotificationNotification *testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:nil rpcNotification:testRequiredStatus]; + SDLRPCNotificationNotification *testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:testManager.statusManager rpcNotification:testRequiredStatus]; +#pragma clang diagnostic pop [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; }); it(@"should have presented the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beTrue()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beTrue()); }); it(@"should not have a vehicle icon", ^{ expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).to(beNil()); }); - - describe(@"when a vehicle icon is received", ^{ - __block UIImage *testIcon = nil; - - beforeEach(^{ - testIcon = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; - }); - - it(@"should have a vehicle icon", ^{ - expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).toNot(beNil()); - expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).to(equal(testIcon)); - }); - }); - + describe(@"when a driver distraction notification is posted with lockScreenDismissableEnabled as true", ^{ __block SDLRPCNotificationNotification *testDriverDistractionNotification = nil; @@ -154,7 +137,7 @@ describe(@"a lock screen manager", ^{ testDriverDistraction = [[SDLOnDriverDistraction alloc] init]; testDriverDistraction.lockScreenDismissalEnabled = @YES; - testDriverDistractionNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeDriverDistractionStateNotification object:nil rpcNotification:testDriverDistraction]; + testDriverDistractionNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeDriverDistractionStateNotification object:dispatcherMock rpcNotification:testDriverDistraction]; [[NSNotificationCenter defaultCenter] postNotification:testDriverDistractionNotification]; }); @@ -205,7 +188,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should have dismissed the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); }); }); @@ -213,49 +196,61 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" __block SDLOnLockScreenStatus *testOffStatus = nil; -#pragma clang diagnostic pop - + beforeEach(^{ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" testOffStatus = [[SDLOnLockScreenStatus alloc] init]; -#pragma clang diagnostic pop testOffStatus.lockScreenStatus = SDLLockScreenStatusOff; - SDLRPCNotificationNotification *testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:nil rpcNotification:testOffStatus]; +#pragma clang diagnostic pop [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; }); it(@"should have dismissed the lock screen", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); }); }); }); }); }); - context(@"with showDeviceLogo as NO", ^{ + context(@"when a vehicle icon is received", ^{ + __block UIImage *testIcon = nil; + SDLLockScreenConfiguration *testsConfig = [SDLLockScreenConfiguration enabledConfiguration]; + beforeEach(^{ - SDLLockScreenConfiguration *config = [SDLLockScreenConfiguration enabledConfiguration]; - config.showDeviceLogo = NO; + testIcon = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; + }); - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakePresenter]; - [testManager start]; + it(@"should should set the vehicle icon on the default lockscreen if showDeviceLogo set to true", ^{ + testsConfig.showDeviceLogo = YES; + fakeViewControllerPresenter.lockViewController = [[SDLLockScreenViewController alloc] init]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testsConfig notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; + + expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).toEventually(equal(testIcon)); }); - describe(@"when a vehicle icon is received", ^{ - __block UIImage *testIcon = nil; + it(@"should should not set the vehicle icon on the default lockscreen if showDeviceLogo set to false", ^{ + testsConfig.showDeviceLogo = NO; + fakeViewControllerPresenter.lockViewController = [[SDLLockScreenViewController alloc] init]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testsConfig notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; - beforeEach(^{ - testIcon = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; - }); + [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; - it(@"should not have a vehicle icon if showDeviceLogo is set to NO", ^{ - expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).to(beNil()); - }); + expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).vehicleIcon).toEventually(beNil()); }); + it(@"should should not modify a custom lockscreen", ^{ + testsConfig.showDeviceLogo = YES; + UIViewController *customLockScreen = [[UIViewController alloc] init]; + fakeViewControllerPresenter.lockViewController = customLockScreen; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testsConfig notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLDidReceiveLockScreenIcon object:nil userInfo:@{ SDLNotificationUserInfoObject: testIcon }]; + + expect(fakeViewControllerPresenter.lockViewController).toEventually(equal(customLockScreen)); + }); }); context(@"with a custom color configuration", ^{ @@ -266,11 +261,11 @@ describe(@"a lock screen manager", ^{ testColor = [UIColor blueColor]; testImage = [UIImage imageNamed:@"testImagePNG" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil]; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithAppIcon:testImage backgroundColor:testColor] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithAppIcon:testImage backgroundColor:testColor] notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -280,7 +275,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should set up the view controller correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).toNot(beNil()); expect(testManager.lockScreenViewController).to(beAnInstanceOf([SDLLockScreenViewController class])); expect(((SDLLockScreenViewController *)testManager.lockScreenViewController).backgroundColor).to(equal(testColor)); @@ -294,11 +289,11 @@ describe(@"a lock screen manager", ^{ beforeEach(^{ testViewController = [[UIViewController alloc] init]; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithViewController:testViewController] notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:[SDLLockScreenConfiguration enabledConfigurationWithViewController:testViewController] notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; }); it(@"should set properties correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).to(beNil()); }); @@ -308,7 +303,7 @@ describe(@"a lock screen manager", ^{ }); it(@"should set up the view controller correctly", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beFalse()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beFalse()); expect(testManager.lockScreenViewController).toNot(beNil()); expect(testManager.lockScreenViewController).toNot(beAnInstanceOf([SDLLockScreenViewController class])); expect(testManager.lockScreenViewController).to(equal(testViewController)); @@ -321,7 +316,7 @@ describe(@"a lock screen manager", ^{ SDLLockScreenConfiguration *config = [SDLLockScreenConfiguration enabledConfiguration]; config.enableDismissGesture = NO; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; [testManager start]; }); @@ -332,8 +327,8 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" SDLOnLockScreenStatus *status = [[SDLOnLockScreenStatus alloc] init]; -#pragma clang diagnostic pop status.lockScreenStatus = SDLLockScreenStatusRequired; +#pragma clang diagnostic pop testManager.lastLockNotification = status; SDLOnDriverDistraction *testDriverDistraction = [[SDLOnDriverDistraction alloc] init]; @@ -351,7 +346,7 @@ describe(@"a lock screen manager", ^{ }); describe(@"with an always enabled configuration", ^{ - __block SDLFakeViewControllerPresenter *fakePresenter = nil; + __block SDLFakeViewControllerPresenter *fakeViewControllerPresenter = nil; __block SDLRPCNotificationNotification *testLockStatusNotification = nil; #pragma clang diagnostic push @@ -360,7 +355,7 @@ describe(@"a lock screen manager", ^{ #pragma clang diagnostic pop beforeEach(^{ - fakePresenter = [[SDLFakeViewControllerPresenter alloc] init]; + fakeViewControllerPresenter = [[SDLFakeViewControllerPresenter alloc] init]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -370,51 +365,50 @@ describe(@"a lock screen manager", ^{ SDLLockScreenConfiguration *config = [SDLLockScreenConfiguration enabledConfiguration]; config.displayMode = SDLLockScreenConfigurationDisplayModeAlways; - testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:nil presenter:fakePresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:config notificationDispatcher:dispatcherMock presenter:fakeViewControllerPresenter]; [testManager start]; }); context(@"receiving a lock screen status of required", ^{ beforeEach(^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testStatus.lockScreenStatus = SDLLockScreenStatusRequired; - testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:nil rpcNotification:testStatus]; + testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:testManager.statusManager rpcNotification:testStatus]; +#pragma clang diagnostic pop [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; }); it(@"should present the lock screen if not already presented", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beTrue()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beTrue()); }); }); context(@"receiving a lock screen status of off", ^{ beforeEach(^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" testStatus.lockScreenStatus = SDLLockScreenStatusOff; - testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:nil rpcNotification:testStatus]; + testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:testManager.statusManager rpcNotification:testStatus]; +#pragma clang diagnostic pop [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; }); it(@"should present the lock screen if not already presented", ^{ - expect(fakePresenter.shouldShowLockScreen).toEventually(beTrue()); + expect(fakeViewControllerPresenter.shouldShowLockScreen).toEventually(beTrue()); }); }); }); describe(@"A lock screen status of OPTIONAL", ^{ - __block SDLLockScreenManager *testLockScreenManager = nil; __block SDLLockScreenConfiguration *testLockScreenConfig = nil; __block id mockViewControllerPresenter = nil; __block SDLRPCNotificationNotification *testLockStatusNotification = nil; beforeEach(^{ mockViewControllerPresenter = OCMClassMock([SDLFakeViewControllerPresenter class]); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - SDLOnLockScreenStatus *testOptionalStatus = [[SDLOnLockScreenStatus alloc] init]; -#pragma clang diagnostic pop - testOptionalStatus.lockScreenStatus = SDLLockScreenStatusOptional; - testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:nil rpcNotification:testOptionalStatus]; testLockScreenConfig = [SDLLockScreenConfiguration enabledConfiguration]; }); @@ -425,19 +419,24 @@ describe(@"a lock screen manager", ^{ testLockScreenConfig.showInOptionalState = true; #pragma clang diagnostic pop - testLockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:testLockScreenConfig notificationDispatcher:nil presenter:mockViewControllerPresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testLockScreenConfig notificationDispatcher:dispatcherMock presenter:mockViewControllerPresenter]; + testManager.canPresent = YES; - [testLockScreenManager start]; // Sets `canPresent` to `true` +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + SDLOnLockScreenStatus *testOptionalStatus = [[SDLOnLockScreenStatus alloc] init]; + testOptionalStatus.lockScreenStatus = SDLLockScreenStatusOptional; + testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:testManager.statusManager rpcNotification:testOptionalStatus]; +#pragma clang diagnostic pop }); it(@"should present the lock screen if not already presented", ^{ OCMStub([mockViewControllerPresenter lockViewController]).andReturn([OCMArg any]); + OCMExpect([mockViewControllerPresenter updateLockScreenToShow:YES withCompletionHandler:[OCMArg any]]).ignoringNonObjectArgs(); [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; - // Since lock screen must be presented/dismissed on the main thread, force the test to execute manually on the main thread. If this is not done, the test case may fail. - [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; - OCMVerify([mockViewControllerPresenter updateLockScreenToShow:YES withCompletionHandler:nil]); + OCMVerifyAllWithDelay(mockViewControllerPresenter, 0.5); }); }); @@ -448,19 +447,24 @@ describe(@"a lock screen manager", ^{ testLockScreenConfig.showInOptionalState = false; #pragma clang diagnostic pop - testLockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:testLockScreenConfig notificationDispatcher:nil presenter:mockViewControllerPresenter]; + testManager = [[SDLLockScreenManager alloc] initWithConfiguration:testLockScreenConfig notificationDispatcher:dispatcherMock presenter:mockViewControllerPresenter]; + testManager.canPresent = YES; - [testLockScreenManager start]; // Sets `canPresent` to `true` +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + SDLOnLockScreenStatus *testOptionalStatus = [[SDLOnLockScreenStatus alloc] init]; + testOptionalStatus.lockScreenStatus = SDLLockScreenStatusOptional; + testLockStatusNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeLockScreenStatusNotification object:testManager.statusManager rpcNotification:testOptionalStatus]; +#pragma clang diagnostic pop }); it(@"should dismiss the lock screen if already presented", ^{ OCMStub([mockViewControllerPresenter lockViewController]).andReturn([OCMArg any]); + OCMExpect([mockViewControllerPresenter updateLockScreenToShow:NO withCompletionHandler:[OCMArg any]]).ignoringNonObjectArgs(); [[NSNotificationCenter defaultCenter] postNotification:testLockStatusNotification]; - // Since lock screen must be presented/dismissed on the main thread, force the test to execute manually on the main thread. If this is not done, the test case may fail. - [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; - OCMVerify([mockViewControllerPresenter updateLockScreenToShow:NO withCompletionHandler:nil]); + OCMVerifyAllWithDelay(mockViewControllerPresenter, 0.5); }); }); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m index ab0640a26..ff9c4e7bb 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m @@ -30,6 +30,7 @@ @property (assign, nonatomic) BOOL hasQueuedUpdate; @property (assign, nonatomic) BOOL waitingOnHMIUpdate; @property (copy, nonatomic) NSArray<SDLMenuCell *> *waitingUpdateMenuCells; +@property (strong, nonatomic, nullable) SDLWindowCapability *windowCapability; @property (assign, nonatomic) UInt32 lastMenuId; @property (copy, nonatomic) NSArray<SDLMenuCell *> *oldMenuCells; @@ -79,12 +80,7 @@ describe(@"menu manager", ^{ windowCapability.imageFields = @[commandIconField]; windowCapability.imageTypeSupported = @[SDLImageTypeDynamic, SDLImageTypeStatic]; windowCapability.menuLayoutsAvailable = @[SDLMenuLayoutList, SDLMenuLayoutTiles]; - - SDLDisplayCapability *displayCapability = [[SDLDisplayCapability alloc] initWithDisplayName:SDLDisplayTypeGeneric]; - displayCapability.windowCapabilities = @[windowCapability]; - - OCMStub(mockSystemCapabilityManager.defaultMainWindowCapability).andReturn(windowCapability); - OCMStub(mockSystemCapabilityManager.displays).andReturn(@[displayCapability]); + testManager.windowCapability = windowCapability; }); it(@"should instantiate correctly", ^{ diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionFilterSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionFilterSpec.m index be190c40d..757c6411b 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionFilterSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionFilterSpec.m @@ -2,6 +2,7 @@ #import <Nimble/Nimble.h> #import "SDLPermissionConstants.h" +#import "SDLPermissionElement.h" #import "SDLPermissionFilter.h" QuickSpecBegin(SDLPermissionFilterSpec) @@ -9,141 +10,148 @@ QuickSpecBegin(SDLPermissionFilterSpec) describe(@"A filter", ^{ __block NSString *testRPCName1 = nil; __block NSString *testRPCName2 = nil; - + __block SDLPermissionElement *testPermissionElement1 = nil; + __block SDLPermissionElement *testPermissionElement2 = nil; + beforeEach(^{ testRPCName1 = @"testRPCName1"; testRPCName2 = @"testRPCName2"; + testPermissionElement1 = [[SDLPermissionElement alloc] initWithRPCName:testRPCName1 parameterPermissions:nil]; + testPermissionElement2 = [[SDLPermissionElement alloc] initWithRPCName:testRPCName2 parameterPermissions:nil]; }); - + describe(@"should initialize correctly", ^{ - __block NSArray<SDLPermissionRPCName> *testRPCNames = nil; + __block NSArray<SDLPermissionElement *> *testPermissionElements = nil; __block SDLPermissionGroupType testGroupType = SDLPermissionGroupTypeAny; __block SDLPermissionFilter *testFilter = nil; - + __block NSDictionary<SDLPermissionRPCName, NSNumber<SDLBool> *> *testObserverReturnChangedDict = nil; - + __block NSDictionary<SDLPermissionRPCName, SDLRPCPermissionStatus *> *testRPCPermissionStatusReturnChangedDict = nil; + beforeEach(^{ - testRPCNames = @[testRPCName1, testRPCName2]; + testPermissionElements = @[testPermissionElement1, testPermissionElement2]; testGroupType = SDLPermissionGroupTypeAny; }); - - context(@"using initWithRPCNames:changeType:observer:", ^{ - beforeEach(^{ - testFilter = [[SDLPermissionFilter alloc] initWithRPCNames:testRPCNames groupType:testGroupType observer:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { - testObserverReturnChangedDict = changedDict; - }]; - }); - - it(@"should set the rpcNames array correctly", ^{ - expect(testFilter.rpcNames).to(equal(testRPCNames)); - }); - - describe(@"it should set up the observer correctly", ^{ - __block NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> *testObserverChangedDict = nil; - __block NSNumber<SDLBool> *testRPCName1Bool = nil; - __block NSNumber<SDLBool> *testRPCName2Bool = nil; - __block SDLPermissionGroupStatus testObserverGroupStatus = SDLPermissionGroupStatusUnknown; - + + context(@"using initWithRPCNames:changeType:permissionsHandler:rpcPermissionStatusHandler", ^{ + context(@"using SDLPermissionsChangedHandler init", ^{ beforeEach(^{ - testRPCName1Bool = @YES; - testRPCName2Bool = @NO; - testObserverChangedDict = @{testRPCName1: testRPCName1Bool, - testRPCName2: testRPCName2Bool}; - testObserverGroupStatus = SDLPermissionGroupStatusMixed; - - testFilter.handler(testObserverChangedDict, testObserverGroupStatus); + testFilter = [[SDLPermissionFilter alloc] initWithPermissions:testPermissionElements groupType:testGroupType permissionsHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { + testObserverReturnChangedDict = change; + }]; }); - - it(@"should call the changedDict correctly", ^{ - expect(testObserverReturnChangedDict).to(equal(testObserverChangedDict)); + + it(@"should set the rpcNames array correctly", ^{ + expect([testFilter rpcNamesFromPermissionElements:testPermissionElements]).to(equal([testFilter rpcNamesFromPermissionElements:testPermissionElements])); }); - - it(@"should call the status correctly", ^{ - expect(@(testObserverGroupStatus)).to(equal(@(testObserverGroupStatus))); + + describe(@"it should set up the observer correctly", ^{ + __block NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> *testObserverChangedDict = nil; + __block NSNumber<SDLBool> *testRPCName1Bool = nil; + __block NSNumber<SDLBool> *testRPCName2Bool = nil; + __block SDLPermissionGroupStatus testObserverGroupStatus = SDLPermissionGroupStatusUnknown; + + beforeEach(^{ + testRPCName1Bool = @YES; + testRPCName2Bool = @NO; + testObserverChangedDict = @{testRPCName1: testRPCName1Bool, + testRPCName2: testRPCName2Bool}; + testObserverGroupStatus = SDLPermissionGroupStatusMixed; + + testFilter.handler(testObserverChangedDict, testObserverGroupStatus); + }); + + it(@"should call the changedDict correctly", ^{ + expect(testObserverReturnChangedDict).to(equal(testObserverChangedDict)); + }); + + it(@"should call the status correctly", ^{ + expect(@(testObserverGroupStatus)).to(equal(@(testObserverGroupStatus))); + }); }); }); - }); - - context(@"using filterWithRPCNames:changeType:observer:", ^{ - beforeEach(^{ - testFilter = [SDLPermissionFilter filterWithRPCNames:testRPCNames groupType:testGroupType observer:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { - testObserverReturnChangedDict = changedDict; - }]; - }); - - it(@"should set the rpcNames array correctly", ^{ - expect(testFilter.rpcNames).to(equal(testRPCNames)); - }); - - describe(@"it should set up the observer correctly", ^{ - __block NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> *testObserverChangedDict = nil; - __block NSNumber<SDLBool> *testRPCName1Bool = nil; - __block NSNumber<SDLBool> *testRPCName2Bool = nil; - __block SDLPermissionGroupStatus testObserverGroupStatus = SDLPermissionGroupStatusUnknown; - + + context(@"using the SDLRPCPermissionStatusChangedHandler init", ^{ beforeEach(^{ - testRPCName1Bool = @YES; - testRPCName2Bool = @NO; - testObserverChangedDict = @{testRPCName1: testRPCName1Bool, - testRPCName2: testRPCName2Bool}; - testObserverGroupStatus = SDLPermissionGroupStatusMixed; - - testFilter.handler(testObserverChangedDict, testObserverGroupStatus); + testFilter = [[SDLPermissionFilter alloc] initWithPermissions:testPermissionElements groupType:testGroupType permissionStatusHandler:^(NSDictionary<SDLRPCFunctionName,SDLRPCPermissionStatus *> * _Nonnull change, SDLPermissionGroupStatus status) { + testRPCPermissionStatusReturnChangedDict = change; + }]; }); - - it(@"should call the changedDict correctly", ^{ - expect(testObserverReturnChangedDict).to(equal(testObserverChangedDict)); + + it(@"should set the permission elements array correctly", ^{ + expect(testFilter.permissionElements).to(equal(testPermissionElements)); }); - - it(@"should call the status correctly", ^{ - expect(@(testObserverGroupStatus)).to(equal(@(testObserverGroupStatus))); + + describe(@"it should set up the observer correctly", ^{ + __block NSDictionary<SDLPermissionRPCName, SDLRPCPermissionStatus *> *testObserverChangedDict = nil; + __block SDLRPCPermissionStatus *rpcPermissionStatus1 = nil; + __block SDLRPCPermissionStatus *rpcPermissionStatus2 = nil; + __block SDLPermissionGroupStatus testObserverGroupStatus = SDLPermissionGroupStatusUnknown; + + beforeEach(^{ + rpcPermissionStatus1 = [[SDLRPCPermissionStatus alloc] initWithRPCName:testRPCName1 isRPCAllowed:YES rpcParameters:nil]; + rpcPermissionStatus2 = [[SDLRPCPermissionStatus alloc] initWithRPCName:testRPCName2 isRPCAllowed:NO rpcParameters:nil]; + testObserverChangedDict = @{testRPCName1: rpcPermissionStatus1, + testRPCName2: rpcPermissionStatus2}; + testObserverGroupStatus = SDLPermissionGroupStatusMixed; + + testFilter.rpcPermissionStatusHandler(testObserverChangedDict, testObserverGroupStatus); + }); + + it(@"should call the changedDict correctly", ^{ + expect(testRPCPermissionStatusReturnChangedDict).to(equal(testObserverChangedDict)); + }); + + it(@"should call the status correctly", ^{ + expect(@(testObserverGroupStatus)).to(equal(@(testObserverGroupStatus))); + }); }); }); }); }); - + describe(@"copying a filter", ^{ __block SDLPermissionFilter *testFilter = nil; __block SDLPermissionFilter *testCopiedFilter = nil; - + beforeEach(^{ - testFilter = [SDLPermissionFilter filterWithRPCNames:@[testRPCName1] groupType:SDLPermissionGroupTypeAny observer:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull changedDict, SDLPermissionGroupStatus status) {}]; + testFilter = [[SDLPermissionFilter alloc] initWithPermissions:@[testPermissionElement1] groupType:SDLPermissionGroupTypeAny permissionsHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) {}]; testCopiedFilter = [testFilter copy]; }); - + it(@"should say copied filters are not the same instance", ^{ expect(testCopiedFilter).toNot(beIdenticalTo(testFilter)); }); - + it(@"should copy the identifier correctly", ^{ expect(testCopiedFilter.identifier).to(equal(testFilter.identifier)); }); - + it(@"should copy the filter array correctly", ^{ - expect(testCopiedFilter.rpcNames).to(equal(testFilter.rpcNames)); + expect(testCopiedFilter.permissionElements).to(equal(testFilter.permissionElements)); }); - + it(@"should copy the change type correctly", ^{ expect(@(testCopiedFilter.groupType)).to(equal(@(testFilter.groupType))); }); }); - + describe(@"testing equality", ^{ __block SDLPermissionFilter *testSameFilter1 = nil; __block SDLPermissionFilter *testSameFilter2 = nil; __block SDLPermissionFilter *testDifferentFilter = nil; - + beforeEach(^{ - testSameFilter1 = [SDLPermissionFilter filterWithRPCNames:@[testRPCName1] groupType:SDLPermissionGroupTypeAny observer:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull changedDict, SDLPermissionGroupStatus status) {}]; + testSameFilter1 = [[SDLPermissionFilter alloc] initWithPermissions:@[testPermissionElement1] groupType:(SDLPermissionGroupType)SDLPermissionGroupTypeAny permissionsHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) {}]; testSameFilter2 = [testSameFilter1 copy]; - - testDifferentFilter = [SDLPermissionFilter filterWithRPCNames:@[testRPCName1] groupType:SDLPermissionGroupTypeAny observer:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull changedDict, SDLPermissionGroupStatus status) {}]; + + testDifferentFilter = [[SDLPermissionFilter alloc] initWithPermissions:@[testPermissionElement1] groupType:(SDLPermissionGroupType)SDLPermissionGroupTypeAny permissionsHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) {}]; }); - + it(@"should say copied filters are the same", ^{ expect(testSameFilter1).to(equal(testSameFilter2)); }); - + it(@"should say new filters are different", ^{ expect(testSameFilter1).toNot(equal(testDifferentFilter)); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m index eaf657595..05020ef37 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m @@ -11,6 +11,7 @@ #import "SDLPermissionFilter.h" #import "SDLPermissionItem.h" #import "SDLPermissionManager.h" +#import "SDLRPCFunctionNames.h" #import "SDLRPCNotificationNotification.h" #import "SDLRPCResponseNotification.h" @@ -27,12 +28,20 @@ QuickSpecBegin(SDLPermissionsManagerSpec) describe(@"SDLPermissionsManager", ^{ __block SDLPermissionManager *testPermissionsManager = nil; - + __block NSString *testRPCNameAllAllowed = nil; __block NSString *testRPCNameAllDisallowed = nil; __block NSString *testRPCNameFullLimitedAllowed = nil; __block NSString *testRPCNameFullLimitedBackgroundAllowed = nil; - + + __block NSString *testRPCParameterNameAllAllowed = nil; + __block NSString *testRPCParameterNameAllDisallowed = nil; + __block NSString *testRPCParameterNameFullLimitedAllowed = nil; + + __block SDLParameterPermissions *testParameterPermissionAllowed = nil; + __block SDLParameterPermissions *testParameterPermissionUserDisallowed = nil; + __block SDLParameterPermissions *testParameterPermissionFullLimitedAllowed = nil; + __block SDLPermissionItem *testPermissionAllAllowed = nil; __block SDLHMIPermissions *testHMIPermissionsAllAllowed = nil; __block SDLPermissionItem *testPermissionAllDisallowed = nil; @@ -41,85 +50,109 @@ describe(@"SDLPermissionsManager", ^{ __block SDLHMIPermissions *testHMIPermissionsFullLimitedAllowed = nil; __block SDLPermissionItem *testPermissionFullLimitedBackgroundAllowed = nil; __block SDLHMIPermissions *testHMIPermissionsFullLimitedBackgroundAllowed = nil; - + __block SDLOnPermissionsChange *testPermissionsChange = nil; - + __block SDLOnHMIStatus *testLimitedHMIStatus = nil; __block SDLOnHMIStatus *testBackgroundHMIStatus = nil; __block SDLOnHMIStatus *testNoneHMIStatus = nil; - + __block SDLRPCNotificationNotification *testPermissionsNotification = nil; __block SDLRPCNotificationNotification *limitedHMINotification = nil; __block SDLRPCNotificationNotification *backgroundHMINotification = nil; __block SDLRPCNotificationNotification *noneHMINotification = nil; - + + __block SDLPermissionElement *testPermissionElementAllAllowed = nil; + __block SDLPermissionElement *testPermissionElementFullLimitedAllowed = nil; + __block SDLPermissionElement *testPermissionElementDisallowed = nil; + beforeEach(^{ // Permission Names testRPCNameAllAllowed = @"AllAllowed"; testRPCNameAllDisallowed = @"AllDisallowed"; testRPCNameFullLimitedAllowed = @"FullAndLimitedAllowed"; testRPCNameFullLimitedBackgroundAllowed = @"FullAndLimitedAndBackgroundAllowed"; - + + // Parameter Permission Names + testRPCParameterNameAllAllowed = @"AllAllowed"; + testRPCParameterNameAllDisallowed = @"AllDisallowed"; + testRPCParameterNameFullLimitedAllowed = @"FullAndLimitedAllowed"; + // Create a manager testPermissionsManager = [[SDLPermissionManager alloc] init]; - + // Permission states testHMIPermissionsAllAllowed = [[SDLHMIPermissions alloc] init]; testHMIPermissionsAllAllowed.allowed = @[SDLHMILevelBackground, SDLHMILevelFull, SDLHMILevelLimited, SDLHMILevelNone]; - + testHMIPermissionsAllDisallowed = [[SDLHMIPermissions alloc] init]; testHMIPermissionsAllDisallowed.userDisallowed = @[SDLHMILevelBackground, SDLHMILevelFull, SDLHMILevelLimited, SDLHMILevelNone]; - + testHMIPermissionsFullLimitedAllowed = [[SDLHMIPermissions alloc] init]; testHMIPermissionsFullLimitedAllowed.allowed = @[SDLHMILevelFull, SDLHMILevelLimited]; testHMIPermissionsFullLimitedAllowed.userDisallowed = @[SDLHMILevelBackground, SDLHMILevelNone]; - + testHMIPermissionsFullLimitedBackgroundAllowed = [[SDLHMIPermissions alloc] init]; testHMIPermissionsFullLimitedBackgroundAllowed.allowed = @[SDLHMILevelFull, SDLHMILevelLimited, SDLHMILevelBackground]; testHMIPermissionsFullLimitedBackgroundAllowed.userDisallowed = @[SDLHMILevelNone]; - + + // Assemble Parameter Permissions + testParameterPermissionAllowed = [[SDLParameterPermissions alloc] init]; + testParameterPermissionAllowed.allowed = @[testRPCParameterNameAllAllowed]; + + testParameterPermissionUserDisallowed = [[SDLParameterPermissions alloc] init]; + testParameterPermissionUserDisallowed.userDisallowed = @[testRPCParameterNameAllDisallowed]; + + testParameterPermissionFullLimitedAllowed = [[SDLParameterPermissions alloc] init]; + testParameterPermissionFullLimitedAllowed.allowed = @[testRPCParameterNameAllAllowed, testRPCParameterNameFullLimitedAllowed]; + // Assemble Permissions SDLParameterPermissions *testParameterPermissions = [[SDLParameterPermissions alloc] init]; - + testPermissionAllAllowed = [[SDLPermissionItem alloc] init]; testPermissionAllAllowed.rpcName = testRPCNameAllAllowed; testPermissionAllAllowed.hmiPermissions = testHMIPermissionsAllAllowed; - testPermissionAllAllowed.parameterPermissions = testParameterPermissions; - + testPermissionAllAllowed.parameterPermissions = testParameterPermissionAllowed; + testPermissionAllDisallowed = [[SDLPermissionItem alloc] init]; testPermissionAllDisallowed.rpcName = testRPCNameAllDisallowed; testPermissionAllDisallowed.hmiPermissions = testHMIPermissionsAllDisallowed; - testPermissionAllDisallowed.parameterPermissions = testParameterPermissions; - + testPermissionAllDisallowed.parameterPermissions = testParameterPermissionUserDisallowed; + testPermissionFullLimitedAllowed = [[SDLPermissionItem alloc] init]; testPermissionFullLimitedAllowed.rpcName = testRPCNameFullLimitedAllowed; testPermissionFullLimitedAllowed.hmiPermissions = testHMIPermissionsFullLimitedAllowed; - testPermissionFullLimitedAllowed.parameterPermissions = testParameterPermissions; - + testPermissionFullLimitedAllowed.parameterPermissions = testParameterPermissionFullLimitedAllowed; + testPermissionFullLimitedBackgroundAllowed = [[SDLPermissionItem alloc] init]; testPermissionFullLimitedBackgroundAllowed.rpcName = testRPCNameFullLimitedBackgroundAllowed; testPermissionFullLimitedBackgroundAllowed.hmiPermissions = testHMIPermissionsFullLimitedBackgroundAllowed; testPermissionFullLimitedBackgroundAllowed.parameterPermissions = testParameterPermissions; - + // Create OnHMIStatus objects testLimitedHMIStatus = [[SDLOnHMIStatus alloc] init]; testLimitedHMIStatus.hmiLevel = SDLHMILevelLimited; - + testBackgroundHMIStatus = [[SDLOnHMIStatus alloc] init]; testBackgroundHMIStatus.hmiLevel = SDLHMILevelBackground; - + testNoneHMIStatus = [[SDLOnHMIStatus alloc] init]; testNoneHMIStatus.hmiLevel = SDLHMILevelNone; - + // Create OnPermissionsChange object testPermissionsChange = [[SDLOnPermissionsChange alloc] init]; testPermissionsChange.permissionItem = @[testPermissionAllAllowed, testPermissionAllDisallowed, testPermissionFullLimitedAllowed, testPermissionFullLimitedBackgroundAllowed]; - + // Permission Notifications testPermissionsNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangePermissionsNotification object:nil rpcNotification:testPermissionsChange]; limitedHMINotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:testLimitedHMIStatus]; backgroundHMINotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:testBackgroundHMIStatus]; noneHMINotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:testNoneHMIStatus]; + + // Permission Elements + testPermissionElementAllAllowed = [[SDLPermissionElement alloc] initWithRPCName:testRPCNameAllAllowed parameterPermissions:@[testRPCParameterNameAllAllowed]]; + testPermissionElementFullLimitedAllowed = [[SDLPermissionElement alloc] initWithRPCName:testRPCNameFullLimitedAllowed parameterPermissions:@[testRPCParameterNameFullLimitedAllowed]]; + testPermissionElementDisallowed = [[SDLPermissionElement alloc] initWithRPCName:testRPCNameAllDisallowed parameterPermissions:@[testRPCParameterNameAllDisallowed]]; }); it(@"should clear when stopped", ^{ @@ -130,165 +163,367 @@ describe(@"SDLPermissionsManager", ^{ expect(testPermissionsManager.currentHMILevel).to(beNil()); expect(testPermissionsManager.requiresEncryption).to(beFalse()); }); - + describe(@"checking if a permission is allowed", ^{ __block NSString *someRPCName = nil; + __block SDLRPCFunctionName someRPCFunctionName = nil; __block BOOL testResultBOOL = NO; - + context(@"when no permissions exist", ^{ - beforeEach(^{ - someRPCName = @"some rpc name"; - - testResultBOOL = [testPermissionsManager isRPCAllowed:someRPCName]; + context(@"deprecated isRPCAllowed: method", ^{ + beforeEach(^{ + someRPCName = @"some rpc name"; + + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultBOOL = [testPermissionsManager isRPCAllowed:someRPCName]; + #pragma clang diagnostic pop + }); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); }); - - it(@"should not be allowed", ^{ - expect(@(testResultBOOL)).to(equal(@NO)); + + context(@"isRPCNameAllowed: method", ^{ + beforeEach(^{ + someRPCFunctionName = @"SomeRPCFunctionName"; + testResultBOOL = [testPermissionsManager isRPCNameAllowed:someRPCName]; + }); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); }); }); - + context(@"when permissions exist but no HMI level", ^{ - beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - - testResultBOOL = [testPermissionsManager isRPCAllowed:testRPCNameAllAllowed]; - }); - - it(@"should not be allowed", ^{ - expect(@(testResultBOOL)).to(equal(@NO)); - }); - }); - - context(@"when permissions exist", ^{ - context(@"and the permission is allowed", ^{ + context(@"deprecated isRPCAllowed: method", ^{ beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" testResultBOOL = [testPermissionsManager isRPCAllowed:testRPCNameAllAllowed]; + #pragma clang diagnostic pop }); - - it(@"should be allowed", ^{ - expect(@(testResultBOOL)).to(equal(@YES)); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); }); }); - - context(@"and the permission is denied", ^{ + + context(@"isRPCNameAllowed: method", ^{ beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - - testResultBOOL = [testPermissionsManager isRPCAllowed:testRPCNameAllDisallowed]; + testResultBOOL = [testPermissionsManager isRPCNameAllowed:someRPCName]; }); - - it(@"should be denied", ^{ - expect(@(testResultBOOL)).to(equal(@NO)); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); + }); + }); + + context(@"when permissions exist", ^{ + context(@"deprecated isRPCAllowed: method", ^{ + context(@"and the permission is allowed", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultBOOL = [testPermissionsManager isRPCAllowed:testRPCNameAllAllowed]; + #pragma clang diagnostic pop + }); + + it(@"should be allowed", ^{ + expect(testResultBOOL).to(beTrue()); + }); + }); + + context(@"and the permission is denied", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultBOOL = [testPermissionsManager isRPCAllowed:testRPCNameAllDisallowed]; + #pragma clang diagnostic pop + }); + + it(@"should be denied", ^{ + expect(testResultBOOL).to(beFalse()); + }); + }); + }); + + context(@"isRPCNameAllowed: method", ^{ + context(@"and the permission is allowed", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultBOOL = [testPermissionsManager isRPCNameAllowed:testRPCNameAllAllowed]; + }); + + it(@"should be allowed", ^{ + expect(testResultBOOL).to(beTrue()); + }); + }); + + context(@"and the permission is denied", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultBOOL = [testPermissionsManager isRPCNameAllowed:testRPCNameAllDisallowed]; + }); + + it(@"should be denied", ^{ + expect(testResultBOOL).to(beFalse()); + }); }); }); }); }); - + describe(@"checking the group status of RPCs", ^{ __block SDLPermissionGroupStatus testResultStatus = SDLPermissionGroupStatusUnknown; - + context(@"with no permissions data", ^{ - beforeEach(^{ - testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + context(@"deprecated groupStatusOfRPCs: method", ^{ + beforeEach(^{ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + #pragma clang diagnostic pop + }); + + it(@"should return unknown", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusUnknown))); + }); }); - - it(@"should return unknown", ^{ - expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusUnknown))); + + context(@"groupStatusOfRPCPermissions: method", ^{ + beforeEach(^{ + testResultStatus = [testPermissionsManager groupStatusOfRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementFullLimitedAllowed]]; + }); + + it(@"should return unknown", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusUnknown))); + }); }); }); - + context(@"for an all allowed group", ^{ - beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; - [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - - testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed]]; + context(@"deprecated groupStatusOfRPCs: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed]]; + #pragma clang diagnostic pop + }); + + it(@"should return allowed", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusAllowed))); + }); }); - - it(@"should return mixed", ^{ - expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusAllowed))); + + context(@"groupStatusOfRPCPermissions: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultStatus = [testPermissionsManager groupStatusOfRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementFullLimitedAllowed]]; + }); + + it(@"should return allowed", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusAllowed))); + }); }); }); - + context(@"for an all disallowed group", ^{ - beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; - [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - - testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameFullLimitedAllowed, testRPCNameAllDisallowed]]; + context(@"deprecated groupStatusOfRPCs: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameFullLimitedAllowed, testRPCNameAllDisallowed]]; + #pragma clang diagnostic pop + }); + + it(@"should return disallowed", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusDisallowed))); + }); }); - - it(@"should return mixed", ^{ - expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusDisallowed))); + + context(@"groupStatusOfRPCPermissions: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultStatus = [testPermissionsManager groupStatusOfRPCPermissions:@[testPermissionElementFullLimitedAllowed, testPermissionElementDisallowed]]; + }); + + it(@"should return disallowed", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusDisallowed))); + }); }); }); - + context(@"for a mixed group", ^{ - beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; - [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - - testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + context(@"deprecated groupStatusOfRPCs: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultStatus = [testPermissionsManager groupStatusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + #pragma clang diagnostic pop + }); + + it(@"should return mixed", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusMixed))); + }); }); - - it(@"should return mixed", ^{ - expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusMixed))); + + context(@"groupStatusOfRPCPermissions: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultStatus = [testPermissionsManager groupStatusOfRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementDisallowed]]; + }); + + it(@"should return mixed", ^{ + expect(@(testResultStatus)).to(equal(@(SDLPermissionGroupStatusMixed))); + }); }); }); }); - + describe(@"checking the status of RPCs", ^{ __block NSDictionary<SDLPermissionRPCName, NSNumber *> *testResultPermissionStatusDict = nil; - + __block NSDictionary<SDLRPCFunctionName, SDLRPCPermissionStatus *> *testResultRPCPermissionStatusDict = nil; + __block SDLRPCPermissionStatus *allowedResultStatus = nil; + __block SDLRPCPermissionStatus *disallowedResultStatus = nil; + + __block NSDictionary *testAllowedDict = nil; + __block SDLRPCPermissionStatus *testAllowedStatus = nil; + __block NSDictionary *testDisallowedDict = nil; + __block SDLRPCPermissionStatus *testDisallowedStatus = nil; + context(@"with no permissions data", ^{ - beforeEach(^{ - testResultPermissionStatusDict = [testPermissionsManager statusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + context(@"deprecated statusOfRPCs: method", ^{ + beforeEach(^{ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultPermissionStatusDict = [testPermissionsManager statusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + #pragma clang diagnostic pop + }); + + it(@"should return correct permission statuses", ^{ + expect(testResultPermissionStatusDict[testRPCNameAllAllowed]).to(equal(@NO)); + expect(testResultPermissionStatusDict[testRPCNameAllDisallowed]).to(equal(@NO)); + }); }); - - it(@"should return correct permission statuses", ^{ - expect(testResultPermissionStatusDict[testRPCNameAllAllowed]).to(equal(@NO)); - expect(testResultPermissionStatusDict[testRPCNameAllDisallowed]).to(equal(@NO)); + + context(@"statusesOfRPCPermissions: method", ^{ + beforeEach(^{ + testResultRPCPermissionStatusDict = [testPermissionsManager statusesOfRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementDisallowed]]; + allowedResultStatus = testResultRPCPermissionStatusDict[testPermissionElementAllAllowed.rpcName]; + disallowedResultStatus = testResultRPCPermissionStatusDict[testPermissionElementDisallowed.rpcName]; + + testAllowedDict = [[NSDictionary alloc] initWithObjectsAndKeys:@(0), testRPCParameterNameAllAllowed, nil]; + testAllowedStatus = [[SDLRPCPermissionStatus alloc] initWithRPCName:testPermissionElementAllAllowed.rpcName isRPCAllowed:YES rpcParameters:testAllowedDict]; + testDisallowedDict = [[NSDictionary alloc] initWithObjectsAndKeys:@(0), testRPCParameterNameAllDisallowed, nil]; + testDisallowedStatus = [[SDLRPCPermissionStatus alloc] initWithRPCName:testPermissionElementDisallowed.rpcName isRPCAllowed:YES rpcParameters:testDisallowedDict]; + }); + + it(@"should return the correct permission statuses", ^{ + expect(allowedResultStatus.rpcName).to(equal(testAllowedStatus.rpcName)); + expect(allowedResultStatus.rpcParameters).to(equal(testAllowedStatus.rpcParameters)); + expect(allowedResultStatus.rpcAllowed).to(equal(@NO)); + + expect(disallowedResultStatus.rpcName).to(equal(testDisallowedStatus.rpcName)); + expect(disallowedResultStatus.rpcParameters).to(equal(testDisallowedStatus.rpcParameters)); + expect(disallowedResultStatus.rpcAllowed).to(equal(@NO)); + }); }); }); - + context(@"with permissions data", ^{ - beforeEach(^{ - [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; - [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - - testResultPermissionStatusDict = [testPermissionsManager statusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + context(@"deprecated statusOfRPCs: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + testResultPermissionStatusDict = [testPermissionsManager statusOfRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed]]; + #pragma clang diagnostic pop + }); + + it(@"should return correct permission statuses", ^{ + expect(testResultPermissionStatusDict[testRPCNameAllAllowed]).to(equal(@YES)); + expect(testResultPermissionStatusDict[testRPCNameAllDisallowed]).to(equal(@NO)); + }); }); - - it(@"should return correct permission statuses", ^{ - expect(testResultPermissionStatusDict[testRPCNameAllAllowed]).to(equal(@YES)); - expect(testResultPermissionStatusDict[testRPCNameAllDisallowed]).to(equal(@NO)); + + context(@"statusesOfRPCPermissions: method", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultRPCPermissionStatusDict = [testPermissionsManager statusesOfRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementDisallowed]]; + + allowedResultStatus = testResultRPCPermissionStatusDict[testPermissionElementAllAllowed.rpcName]; + disallowedResultStatus = testResultRPCPermissionStatusDict[testPermissionElementDisallowed.rpcName]; + + testAllowedDict = [[NSDictionary alloc] initWithObjectsAndKeys:@(1), testRPCParameterNameAllAllowed, nil]; + testAllowedStatus = [[SDLRPCPermissionStatus alloc] initWithRPCName:testPermissionElementAllAllowed.rpcName isRPCAllowed:YES rpcParameters:testAllowedDict]; + + testDisallowedDict = [[NSDictionary alloc] initWithObjectsAndKeys:@(0), testRPCParameterNameAllDisallowed, nil]; + testDisallowedStatus = [[SDLRPCPermissionStatus alloc] initWithRPCName:testPermissionElementDisallowed.rpcName isRPCAllowed:NO rpcParameters:testDisallowedDict]; + }); + + it(@"should return the correct permission statuses", ^{ + expect(allowedResultStatus.rpcName).to(equal(testAllowedStatus.rpcName)); + expect(allowedResultStatus.rpcParameters).to(equal(testAllowedStatus.rpcParameters)); + expect(allowedResultStatus.rpcAllowed).to(equal(testAllowedStatus.rpcAllowed)); + + expect(disallowedResultStatus.rpcName).to(equal(testDisallowedStatus.rpcName)); + expect(disallowedResultStatus.rpcParameters).to(equal(testDisallowedStatus.rpcParameters)); + expect(disallowedResultStatus.rpcAllowed).to(equal(testDisallowedStatus.rpcAllowed)); + }); }); }); }); - + describe(@"adding and using observers", ^{ describe(@"adding new observers", ^{ context(@"when no data is present", ^{ __block BOOL testObserverCalled = NO; __block SDLPermissionGroupStatus testObserverStatus = SDLPermissionGroupStatusUnknown; __block NSDictionary<SDLPermissionRPCName,NSNumber *> *testObserverChangeDict = nil; - + beforeEach(^{ testObserverCalled = NO; testObserverStatus = SDLPermissionGroupStatusUnknown; testObserverChangeDict = nil; - + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { testObserverChangeDict = change; testObserverStatus = status; testObserverCalled = YES; }]; + #pragma clang diagnostic pop }); - + it(@"should return correct permission statuses", ^{ expect(@(testObserverCalled)).to(equal(@YES)); expect(@(testObserverStatus)).to(equal(@(SDLPermissionGroupStatusUnknown))); @@ -296,30 +531,33 @@ describe(@"SDLPermissionsManager", ^{ expect(testObserverChangeDict[testRPCNameAllDisallowed]).to(equal(@NO)); }); }); - + context(@"when data is already present", ^{ __block NSInteger numberOfTimesObserverCalled = 0; __block NSDictionary<SDLPermissionRPCName,NSNumber *> *testObserverBlockChangedDict = nil; __block SDLPermissionGroupStatus testObserverReturnStatus = SDLPermissionGroupStatusUnknown; - + context(@"to match an ANY observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - + // This should be called twice, once for each RPC being observed. It should be called immediately since data should already be present + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName, NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; testObserverBlockChangedDict = changedDict; testObserverReturnStatus = status; }]; + #pragma clang diagnostic pop }); - + it(@"should call the observer with proper status", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); expect(testObserverBlockChangedDict[testRPCNameAllAllowed]).to(equal(@YES)); @@ -328,25 +566,28 @@ describe(@"SDLPermissionsManager", ^{ expect(@(testObserverReturnStatus)).to(equal(@(SDLPermissionGroupStatusMixed))); }); }); - + context(@"to match an all allowed observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level LIMITED [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - + // This should be called twice, once for each RPC being observed. It should be called immediately since data should already be present + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; testObserverBlockChangedDict = change; testObserverReturnStatus = status; }]; + #pragma clang diagnostic pop }); - + it(@"should call the observer with proper status", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); expect(testObserverBlockChangedDict[testRPCNameAllAllowed]).to(equal(@YES)); @@ -355,24 +596,27 @@ describe(@"SDLPermissionsManager", ^{ expect(@(testObserverReturnStatus)).to(equal(@(SDLPermissionGroupStatusAllowed))); }); }); - + context(@"that does not match an all allowed observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level NONE [[NSNotificationCenter defaultCenter] postNotification:noneHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - + // This should be called twice, once for each RPC being observed. It should be called immediately since data should already be present + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllDisallowed, testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; testObserverReturnStatus = status; }]; + #pragma clang diagnostic pop }); - + it(@"should call the observer with status Disallowed", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); expect(@(testObserverReturnStatus)).to(equal(@(SDLPermissionGroupStatusDisallowed))); @@ -380,74 +624,116 @@ describe(@"SDLPermissionsManager", ^{ }); }); }); - + + describe(@"adding a new observer with subscribeToRPCPermissions:groupType:Handler", ^{ + context(@"when no data is present", ^{ + __block BOOL testObserverCalled = NO; + + beforeEach(^{ + testObserverCalled = NO; + [testPermissionsManager subscribeToRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { + testObserverCalled = YES; + }]; + }); + + it(@"should be called", ^{ + expect(testObserverCalled).to(beTrue()); + }); + }); + + context(@"when data is present", ^{ + __block BOOL testObserverCalled = NO; + + beforeEach(^{ + testObserverCalled = NO; + + // Post the notification before setting the observer to make sure data is already present + // HMI Full & Limited allowed + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + // This should not be called even with data currently present, the handler will only be called when an permissions update occurs after the RPC is subscribed to + [testPermissionsManager subscribeToRPCPermissions:@[testPermissionElementAllAllowed, testPermissionElementDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { + testObserverCalled = YES; + }]; + }); + + it(@"should be called", ^{ + expect(@(testObserverCalled)).to(beTrue()); + }); + }); + }); + context(@"updating an observer with new permission data", ^{ __block NSInteger numberOfTimesObserverCalled = 0; - + __block SDLOnPermissionsChange *testPermissionChangeUpdate = nil; __block SDLPermissionItem *testPermissionUpdated = nil; __block NSMutableArray<NSDictionary<SDLPermissionRPCName,NSNumber*> *> *changeDicts = nil; __block NSMutableArray<NSNumber<SDLUInt> *> *testStatuses = nil; - + context(@"to match an ANY observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; changeDicts = [NSMutableArray array]; testStatuses = [NSMutableArray array]; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level LIMITED [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - + // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:changedDict]; }]; - + #pragma clang diagnostic pop + // Create a permission update disallowing our current HMI level for the observed permission SDLParameterPermissions *testParameterPermissions = [[SDLParameterPermissions alloc] init]; SDLHMIPermissions *testHMIPermissionsUpdated = [[SDLHMIPermissions alloc] init]; testHMIPermissionsUpdated.allowed = @[SDLHMILevelBackground, SDLHMILevelFull]; testHMIPermissionsUpdated.userDisallowed = @[SDLHMILevelLimited, SDLHMILevelNone]; - + testPermissionUpdated = [[SDLPermissionItem alloc] init]; testPermissionUpdated.rpcName = testRPCNameAllAllowed; testPermissionUpdated.hmiPermissions = testHMIPermissionsUpdated; testPermissionUpdated.parameterPermissions = testParameterPermissions; - + testPermissionChangeUpdate = [[SDLOnPermissionsChange alloc] init]; testPermissionChangeUpdate.permissionItem = [NSArray arrayWithObject:testPermissionUpdated]; - + // Send the permission update SDLRPCNotificationNotification *updatedNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangePermissionsNotification object:nil rpcNotification:testPermissionChangeUpdate]; [[NSNotificationCenter defaultCenter] postNotification:updatedNotification]; }); - + it(@"should call the observer twice", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); }); - + it(@"should have proper data in the first change dict", ^{ expect(changeDicts[0].allKeys).to(contain(testRPCNameAllAllowed)); expect(changeDicts[0].allKeys).to(contain(testRPCNameAllDisallowed)); - + NSNumber<SDLBool> *allAllowed = changeDicts[0][testRPCNameAllAllowed]; expect(allAllowed).to(equal(@YES)); - + NSNumber<SDLBool> *allDisallowed = changeDicts[0][testRPCNameAllDisallowed]; expect(allDisallowed).to(equal(@NO)); }); - + it(@"should have the proper data in the second change dict", ^{ expect(changeDicts[1].allKeys).to(contain(testRPCNameAllAllowed)); expect(changeDicts[1].allKeys).to(contain(testRPCNameAllDisallowed)); - + NSNumber<SDLBool> *allAllowed = changeDicts[1][testRPCNameAllAllowed]; expect(allAllowed).to(equal(@NO)); - + NSNumber<SDLBool> *allDisallowed = changeDicts[1][testRPCNameAllDisallowed]; expect(allDisallowed).to(equal(@NO)); }); @@ -483,188 +769,200 @@ describe(@"SDLPermissionsManager", ^{ }); }); }); - + context(@"to match an all allowed observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; changeDicts = [NSMutableArray array]; testStatuses = [NSMutableArray array]; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level BACKGROUND [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + context(@"so that it becomes All Allowed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllDisallowed, testRPCNameFullLimitedBackgroundAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:change]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + // Create a permission update allowing our current HMI level for the observed permission SDLParameterPermissions *testParameterPermissions = [[SDLParameterPermissions alloc] init]; SDLHMIPermissions *testHMIPermissionsUpdated = [[SDLHMIPermissions alloc] init]; testHMIPermissionsUpdated.allowed = @[SDLHMILevelLimited, SDLHMILevelNone, SDLHMILevelBackground, SDLHMILevelFull]; testHMIPermissionsUpdated.userDisallowed = @[]; - + testPermissionUpdated = [[SDLPermissionItem alloc] init]; testPermissionUpdated.rpcName = testRPCNameAllDisallowed; testPermissionUpdated.hmiPermissions = testHMIPermissionsUpdated; testPermissionUpdated.parameterPermissions = testParameterPermissions; - + testPermissionChangeUpdate = [[SDLOnPermissionsChange alloc] init]; testPermissionChangeUpdate.permissionItem = [NSArray arrayWithObject:testPermissionUpdated]; - + // Send the permission update SDLRPCNotificationNotification *updatedNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangePermissionsNotification object:nil rpcNotification:testPermissionChangeUpdate]; [[NSNotificationCenter defaultCenter] postNotification:updatedNotification]; }); - + it(@"should call the observer twice", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); }); - + it(@"should have proper data in the first change dict", ^{ expect(changeDicts[0].allKeys).to(haveCount(@2)); expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusMixed))); }); - + it(@"should have the proper data in the second change dict", ^{ expect(changeDicts[1].allKeys).to(haveCount(@2)); expect(testStatuses[1]).to(equal(@(SDLPermissionGroupStatusAllowed))); }); }); - + context(@"so that it goes from All Allowed to mixed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:change]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + // Create a permission update disallowing our current HMI level for the observed permission SDLParameterPermissions *testParameterPermissions = [[SDLParameterPermissions alloc] init]; SDLHMIPermissions *testHMIPermissionsUpdated = [[SDLHMIPermissions alloc] init]; testHMIPermissionsUpdated.allowed = @[]; testHMIPermissionsUpdated.userDisallowed = @[SDLHMILevelBackground, SDLHMILevelFull, SDLHMILevelLimited, SDLHMILevelNone]; - + testPermissionUpdated = [[SDLPermissionItem alloc] init]; testPermissionUpdated.rpcName = testRPCNameAllAllowed; testPermissionUpdated.hmiPermissions = testHMIPermissionsUpdated; testPermissionUpdated.parameterPermissions = testParameterPermissions; - + testPermissionChangeUpdate = [[SDLOnPermissionsChange alloc] init]; testPermissionChangeUpdate.permissionItem = [NSArray arrayWithObject:testPermissionUpdated]; - + // Send the permission update SDLRPCNotificationNotification *updatedNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangePermissionsNotification object:nil rpcNotification:testPermissionChangeUpdate]; [[NSNotificationCenter defaultCenter] postNotification:updatedNotification]; }); - + it(@"should call the observer twice", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); }); - + it(@"should have proper data in the first change dict", ^{ expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusAllowed))); expect(changeDicts[0].allKeys).to(contain(testRPCNameAllAllowed)); - + NSNumber<SDLBool> *isAllowed = changeDicts[0][testRPCNameAllAllowed]; expect(isAllowed).to(equal(@YES)); }); - + it(@"should have the proper data in the second change dict", ^{ expect(testStatuses[1]).to(equal(@(SDLPermissionGroupStatusDisallowed))); expect(changeDicts[1].allKeys).to(contain(testRPCNameAllAllowed)); - + NSNumber<SDLBool> *isAllowed = changeDicts[1][testRPCNameAllAllowed]; expect(isAllowed).to(equal(@NO)); }); }); }); - + context(@"to not match an all allowed observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; changeDicts = [NSMutableArray array]; testStatuses = [NSMutableArray array]; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level BACKGROUND [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + context(@"from mixed to disallowed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:change]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + // Create a permission update disallowing our current HMI level for the observed permission SDLParameterPermissions *testParameterPermissions = [[SDLParameterPermissions alloc] init]; SDLHMIPermissions *testHMIPermissionsUpdated = [[SDLHMIPermissions alloc] init]; testHMIPermissionsUpdated.allowed = @[]; testHMIPermissionsUpdated.userDisallowed = @[SDLHMILevelBackground, SDLHMILevelFull, SDLHMILevelLimited, SDLHMILevelNone]; - + testPermissionUpdated = [[SDLPermissionItem alloc] init]; testPermissionUpdated.rpcName = testRPCNameAllAllowed; testPermissionUpdated.hmiPermissions = testHMIPermissionsUpdated; testPermissionUpdated.parameterPermissions = testParameterPermissions; - + testPermissionChangeUpdate = [[SDLOnPermissionsChange alloc] init]; testPermissionChangeUpdate.permissionItem = [NSArray arrayWithObject:testPermissionUpdated]; - + // Send the permission update SDLRPCNotificationNotification *updatedNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangePermissionsNotification object:nil rpcNotification:testPermissionChangeUpdate]; [[NSNotificationCenter defaultCenter] postNotification:updatedNotification]; }); - + it(@"should call the observer with a mixed status", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusMixed))); }); }); - + context(@"from disallowed to mixed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameFullLimitedAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull change, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:change]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + // Create a permission update disallowing our current HMI level for the observed permission SDLParameterPermissions *testParameterPermissions = [[SDLParameterPermissions alloc] init]; SDLHMIPermissions *testHMIPermissionsUpdated = [[SDLHMIPermissions alloc] init]; testHMIPermissionsUpdated.allowed = @[SDLHMILevelLimited, SDLHMILevelBackground]; testHMIPermissionsUpdated.userDisallowed = @[SDLHMILevelFull, SDLHMILevelNone]; - + testPermissionUpdated = [[SDLPermissionItem alloc] init]; testPermissionUpdated.rpcName = testRPCNameAllAllowed; testPermissionUpdated.hmiPermissions = testHMIPermissionsUpdated; testPermissionUpdated.parameterPermissions = testParameterPermissions; - + testPermissionChangeUpdate = [[SDLOnPermissionsChange alloc] init]; testPermissionChangeUpdate.permissionItem = [NSArray arrayWithObject:testPermissionUpdated]; - + // Send the permission update SDLRPCNotificationNotification *updatedNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangePermissionsNotification object:nil rpcNotification:testPermissionChangeUpdate]; [[NSNotificationCenter defaultCenter] postNotification:updatedNotification]; }); - + it(@"should call the observer", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusDisallowed))); @@ -672,173 +970,188 @@ describe(@"SDLPermissionsManager", ^{ }); }); }); - + context(@"updating an observer with a new HMI level", ^{ __block NSInteger numberOfTimesObserverCalled = 0; __block NSMutableArray<NSDictionary<SDLPermissionRPCName,NSNumber *> *> *changeDicts = nil; __block NSMutableArray<NSNumber<SDLUInt> *> *testStatuses = nil; - + context(@"to match an ANY observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; changeDicts = [NSMutableArray array]; testStatuses = [NSMutableArray array]; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level BACKGROUND [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; - + // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:changedDict]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + // Upgrade the HMI level to LIMITED [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; }); - + it(@"should call the observer twice", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); }); - + it(@"should have proper data in the first change dict", ^{ NSNumber<SDLBool> *allAllowed = changeDicts[0][testRPCNameAllAllowed]; expect(allAllowed).to(equal(@YES)); - + NSNumber<SDLBool> *fullLimitedAllowed = changeDicts[0][testRPCNameFullLimitedAllowed]; expect(fullLimitedAllowed).to(equal(@NO)); - + expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusMixed))); }); - + it(@"should have the proper data in the second change dict", ^{ NSNumber<SDLBool> *allAllowed = changeDicts[1][testRPCNameAllAllowed]; expect(allAllowed).to(equal(@YES)); - + NSNumber<SDLBool> *fullLimitedAllowed = changeDicts[1][testRPCNameFullLimitedAllowed]; expect(fullLimitedAllowed).to(equal(@YES)); - + expect(testStatuses[1]).to(equal(@(SDLPermissionGroupStatusAllowed))); }); }); - + context(@"to match an all allowed observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; changeDicts = [NSMutableArray array]; testStatuses = [NSMutableArray array]; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level BACKGROUND [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + context(@"so that it becomes All Allowed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:changedDict]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; }); - + it(@"should call the observer", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); - + expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusDisallowed))); expect(testStatuses[1]).to(equal(@(SDLPermissionGroupStatusAllowed))); }); }); - + context(@"so that it goes from All Allowed to at least some disallowed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameFullLimitedBackgroundAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:changedDict]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + [[NSNotificationCenter defaultCenter] postNotification:noneHMINotification]; }); - + it(@"should call the observer twice", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); }); - + it(@"should have proper data in the first change dict", ^{ expect(changeDicts[0].allKeys).to(contain(testRPCNameFullLimitedBackgroundAllowed)); - + NSNumber<SDLBool> *isAllowed = changeDicts[0][testRPCNameFullLimitedBackgroundAllowed]; expect(isAllowed).to(equal(@YES)); - + expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusAllowed))); }); - + it(@"should have the proper data in the second change dict", ^{ expect(changeDicts[1].allKeys).to(contain(testRPCNameFullLimitedBackgroundAllowed)); - + NSNumber<SDLBool> *isAllowed = changeDicts[1][testRPCNameFullLimitedBackgroundAllowed]; expect(isAllowed).to(equal(@NO)); - + expect(testStatuses[1]).to(equal(@(SDLPermissionGroupStatusDisallowed))); }); }); }); - + context(@"to not match an all allowed observer", ^{ beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; changeDicts = [NSMutableArray array]; testStatuses = [NSMutableArray array]; - + // Post the notification before setting the observer to make sure data is already present // HMI Full & Limited allowed, hmi level BACKGROUND [[NSNotificationCenter defaultCenter] postNotification:backgroundHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + context(@"that goes from disallowed to mixed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameFullLimitedAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:changedDict]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; }); - + it(@"should call the observer", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); - + expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusDisallowed))); }); }); - + context(@"that goes from mixed to disallowed", ^{ beforeEach(^{ // Set an observer that should be called immediately for the preexisting data, then called again when new data is sent + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameFullLimitedAllowed, testRPCNameFullLimitedBackgroundAllowed] groupType:SDLPermissionGroupTypeAllAllowed withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; [changeDicts addObject:changedDict]; [testStatuses addObject:@(status)]; }]; - + #pragma clang diagnostic pop + [[NSNotificationCenter defaultCenter] postNotification:noneHMINotification]; }); - + it(@"should call the observer", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); expect(testStatuses[0]).to(equal(@(SDLPermissionGroupStatusMixed))); @@ -847,86 +1160,180 @@ describe(@"SDLPermissionsManager", ^{ }); }); }); - + + describe(@"checking parameter permissions", ^{ + __block SDLRPCFunctionName someRPCFunctionName = nil; + __block NSString *someRPCParameterName = nil; + __block BOOL testResultBOOL = NO; + + context(@"when no permissions exist", ^{ + beforeEach(^{ + someRPCFunctionName = @"SomeRPCFunctionName"; + someRPCParameterName = @"SomeRPCParameterName"; + testResultBOOL = [testPermissionsManager isPermissionParameterAllowed:someRPCFunctionName parameter:someRPCParameterName]; + }); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); + }); + + context(@"when permissions exist but no HMI level", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + testResultBOOL = [testPermissionsManager isPermissionParameterAllowed:testRPCNameAllAllowed parameter:testRPCParameterNameAllAllowed]; + }); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); + }); + + context(@"when permissions exist and HMI level exists", ^{ + context(@"and the parameter permission is allowed", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultBOOL = [testPermissionsManager isPermissionParameterAllowed:testRPCNameAllAllowed parameter:testRPCParameterNameAllAllowed]; + }); + + it(@"should be allowed", ^{ + expect(testResultBOOL).to(beTrue()); + }); + }); + + context(@"and the parameter permission is denied", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultBOOL = [testPermissionsManager isPermissionParameterAllowed:testRPCNameAllDisallowed parameter:testRPCParameterNameAllDisallowed]; + }); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); + }); + + context(@"when user disallowed parameter permissions is not nil", ^{ + context(@"and the parameter is disallowed", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultBOOL = [testPermissionsManager isPermissionParameterAllowed:testRPCNameFullLimitedAllowed parameter:testRPCParameterNameAllDisallowed]; + }); + + it(@"should not be allowed", ^{ + expect(testResultBOOL).to(beFalse()); + }); + }); + + context(@"and the parameter is allowed", ^{ + beforeEach(^{ + [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; + [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; + + testResultBOOL = [testPermissionsManager isPermissionParameterAllowed:testRPCNameFullLimitedAllowed parameter:testRPCParameterNameAllAllowed]; + }); + + it(@"should be allowed", ^{ + expect(testResultBOOL).to(beTrue()); + }); + }); + }); + }); + }); + describe(@"removing observers", ^{ context(@"removing the only observer", ^{ __block NSInteger numberOfTimesObserverCalled = 0; - + beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; - + // Add two observers + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" NSUUID *observerId = [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName, NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; }]; - + #pragma clang diagnostic pop + // Remove one observer [testPermissionsManager removeObserverForIdentifier:observerId]; - + // Post a notification [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + it(@"should only call the observer once", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@1)); }); }); - + context(@"removing a single observer and leaving one remaining", ^{ __block NSUInteger numberOfTimesObserverCalled = 0; - + beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; - + // Add two observers + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" NSUUID *testRemovedObserverId = [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; }]; - + [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameFullLimitedAllowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; }]; - + #pragma clang diagnostic pop + // Remove one observer [testPermissionsManager removeObserverForIdentifier:testRemovedObserverId]; - + // Post a notification [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + it(@"should call three observers", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@3)); }); }); - + context(@"removing all observers", ^{ __block NSInteger numberOfTimesObserverCalled = 0; - + beforeEach(^{ // Reset vars numberOfTimesObserverCalled = 0; - + // Add two observers + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; }]; - + [testPermissionsManager addObserverForRPCs:@[testRPCNameAllAllowed, testRPCNameAllDisallowed] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber *> * _Nonnull changedDict, SDLPermissionGroupStatus status) { numberOfTimesObserverCalled++; }]; - + #pragma clang diagnostic pop + // Remove all observers [testPermissionsManager removeAllObservers]; - + // Add some permissions [[NSNotificationCenter defaultCenter] postNotification:limitedHMINotification]; [[NSNotificationCenter defaultCenter] postNotification:testPermissionsNotification]; }); - + it(@"should not call the observer", ^{ expect(@(numberOfTimesObserverCalled)).to(equal(@2)); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLSequentialRPCRequestOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLSequentialRPCRequestOperationSpec.m index 0c121d22c..9f3f5cc93 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLSequentialRPCRequestOperationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLSequentialRPCRequestOperationSpec.m @@ -51,9 +51,9 @@ describe(@"Sending sequential requests", ^{ testOperation = [[SDLSequentialRPCRequestOperation alloc] initWithConnectionManager:testConnectionManager requests:sendRequests.copy progressHandler:^BOOL(__kindof SDLRPCRequest * _Nonnull request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error, float percentComplete) { TestRequestProgressResponse *progressResponse = testProgressResponses[request.correlationID]; - expect(progressResponse.percentComplete).to(beCloseTo(percentComplete)); - expect(response).toNot(beNil()); - expect(error).to(beNil()); + expect(progressResponse.percentComplete).toEventually(beCloseTo(percentComplete)); + expect(response).toEventuallyNot(beNil()); + expect(error).toEventually(beNil()); [resultResponses addObject:response]; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m index 730af59f7..4f708087b 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonManagerSpec.m @@ -167,6 +167,7 @@ describe(@"a soft button manager", ^{ testObject2 = [[SDLSoftButtonObject alloc] initWithName:object2Name state:object2State1 handler:nil]; testManager.softButtonObjects = @[testObject1, testObject2]; + [NSThread sleepForTimeInterval:0.1]; }); it(@"should set soft buttons correctly", ^{ diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonStateSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonStateSpec.m index e62a9256f..0d89b53b0 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonStateSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLSoftButtonStateSpec.m @@ -51,7 +51,7 @@ describe(@"soft button state", ^{ SDLSoftButton *testSoftButton = testState.softButton; expect(testSoftButton.type).to(equal(SDLSoftButtonTypeBoth)); -// expect(testSoftButton.handler).to(beNil()); + expect((id)testSoftButton.handler).to(beNil()); expect(testSoftButton.softButtonID).to(equal(0)); expect(testSoftButton.isHighlighted).to(beFalsy()); expect(testSoftButton.systemAction).to(equal(SDLSystemActionDefaultAction)); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m index 69e9cea80..93d5e5829 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m @@ -2,6 +2,7 @@ #import <Nimble/Nimble.h> #import <OCMock/OCMock.h> +#import "SDLAudioStreamManager.h" #import "SDLConfiguration.h" #import "SDLControlFramePayloadAudioStartServiceAck.h" #import "SDLDisplayCapabilities.h" @@ -22,9 +23,12 @@ #import "SDLVehicleType.h" #import "TestConnectionManager.h" + @interface SDLStreamingAudioLifecycleManager() -@property (copy, nonatomic) NSString *connectedVehicleMake; +@property (weak, nonatomic) SDLProtocol *protocol; +@property (copy, nonatomic, nullable) NSString *connectedVehicleMake; +@property (nonatomic, strong, readwrite) SDLAudioStreamManager *audioTranscodingManager; @end @@ -34,6 +38,7 @@ describe(@"the streaming audio manager", ^{ __block SDLStreamingAudioLifecycleManager *streamingLifecycleManager = nil; __block SDLConfiguration *testConfig = nil; __block TestConnectionManager *testConnectionManager = nil; + __block SDLAudioStreamManager *mockAudioStreamManager = nil; __block SDLSystemCapabilityManager *testSystemCapabilityManager = nil; __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel) = ^(SDLHMILevel hmiLevel) { @@ -41,19 +46,20 @@ describe(@"the streaming audio manager", ^{ hmiStatus.hmiLevel = hmiLevel; SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:hmiStatus]; [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.3]; }; beforeEach(^{ testConfig = OCMClassMock([SDLConfiguration class]); testConnectionManager = [[TestConnectionManager alloc] init]; + testSystemCapabilityManager = OCMClassMock([SDLSystemCapabilityManager class]); streamingLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfig systemCapabilityManager:testSystemCapabilityManager]; + mockAudioStreamManager = OCMClassMock([SDLAudioStreamManager class]); + streamingLifecycleManager.audioTranscodingManager = mockAudioStreamManager; }); it(@"should initialize properties", ^{ - expect(streamingLifecycleManager.audioManager).toNot(beNil()); + expect(streamingLifecycleManager.audioTranscodingManager).toNot(beNil()); expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@NO)); expect(@(streamingLifecycleManager.isAudioConnected)).to(equal(@NO)); expect(@(streamingLifecycleManager.isAudioEncrypted)).to(equal(@NO)); @@ -105,11 +111,10 @@ describe(@"the streaming audio manager", ^{ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:someRegisterAppInterfaceResponse]; [[NSNotificationCenter defaultCenter] postNotification:notification]; - [NSThread sleepForTimeInterval:0.1]; }); it(@"should should save the connected vehicle make", ^{ - expect(streamingLifecycleManager.connectedVehicleMake).to(equal(testVehicleType.make)); + expect(streamingLifecycleManager.connectedVehicleMake).toEventually(equal(testVehicleType.make)); }); }); @@ -141,7 +146,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should close the streams", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateShuttingDown)); }); }); @@ -151,7 +156,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateShuttingDown)); }); }); @@ -161,7 +166,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateReady)); }); }); @@ -171,7 +176,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateReady)); }); }); }); @@ -200,7 +205,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should close the streams", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateShuttingDown)); }); }); @@ -210,7 +215,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateShuttingDown)); }); }); @@ -220,7 +225,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateReady)); }); }); @@ -230,7 +235,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateReady)); }); }); }); @@ -252,7 +257,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should not start the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateStopped)); }); }); @@ -262,7 +267,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should not start the stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateStopped)); }); }); @@ -272,7 +277,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should start the streams", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStarting)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateStarting)); }); }); @@ -282,7 +287,7 @@ describe(@"the streaming audio manager", ^{ }); it(@"should start the streams", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStarting)); + expect(streamingLifecycleManager.currentAudioStreamState).toEventually(equal(SDLAudioStreamManagerStateStarting)); }); }); }); @@ -306,7 +311,7 @@ describe(@"the streaming audio manager", ^{ testAudioStartServicePayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithMTU:testMTU]; testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:testAudioStartServicePayload.data]; - [streamingLifecycleManager handleProtocolStartServiceACKMessage:testAudioMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceACK:testAudioMessage]; }); it(@"should have set all the right properties", ^{ @@ -330,7 +335,7 @@ describe(@"the streaming audio manager", ^{ testAudioHeader.serviceType = SDLServiceTypeAudio; testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil]; - [streamingLifecycleManager handleProtocolEndServiceACKMessage:testAudioMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceACK:testAudioMessage]; }); it(@"should have set all the right properties", ^{ @@ -352,7 +357,7 @@ describe(@"the streaming audio manager", ^{ testAudioHeader.serviceType = SDLServiceTypeAudio; testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil]; - [streamingLifecycleManager handleProtocolEndServiceACKMessage:testAudioMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceACK:testAudioMessage]; }); it(@"should have set all the right properties", ^{ @@ -374,7 +379,7 @@ describe(@"the streaming audio manager", ^{ testAudioHeader.serviceType = SDLServiceTypeAudio; testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil]; - [streamingLifecycleManager handleProtocolEndServiceNAKMessage:testAudioMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceNAK:testAudioMessage]; }); it(@"should have set all the right properties", ^{ @@ -382,6 +387,112 @@ describe(@"the streaming audio manager", ^{ }); }); }); + + describe(@"attempting to stop the manager", ^{ + __block BOOL handlerCalled = NO; + + beforeEach(^{ + handlerCalled = NO; + [streamingLifecycleManager endAudioServiceWithCompletionHandler:^ { + handlerCalled = YES; + }]; + streamingLifecycleManager.connectedVehicleMake = @"OEM_make_2"; + }); + + context(@"when the manager is READY", ^{ + beforeEach(^{ + [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateReady fromOldState:nil callEnterTransition:NO]; + [streamingLifecycleManager stop]; + }); + + it(@"should transition to the stopped state and reset the saved properties", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped)); + + expect(streamingLifecycleManager.protocol).to(beNil()); + expect(streamingLifecycleManager.hmiLevel).to(equal(SDLHMILevelNone)); + expect(streamingLifecycleManager.connectedVehicleMake).to(beNil()); + OCMVerify([mockAudioStreamManager stop]); + expect(handlerCalled).to(beTrue()); + }); + }); + + context(@"when the manager is already stopped", ^{ + beforeEach(^{ + [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateStopped fromOldState:nil callEnterTransition:NO]; + [streamingLifecycleManager stop]; + }); + + it(@"should stay in the stopped state", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped)); + + expect(streamingLifecycleManager.protocol).to(beNil()); + expect(streamingLifecycleManager.hmiLevel).to(equal(SDLHMILevelNone)); + expect(streamingLifecycleManager.connectedVehicleMake).to(beNil()); + OCMReject([mockAudioStreamManager stop]); + expect(handlerCalled).to(beFalse()); + }); + }); + }); + + describe(@"starting the manager when it's STOPPED", ^{ + __block SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]); + + beforeEach(^{ + [streamingLifecycleManager startWithProtocol:protocolMock]; + [streamingLifecycleManager endAudioServiceWithCompletionHandler:^{}]; + }); + + context(@"when stopping the audio service due to a secondary transport shutdown", ^{ + beforeEach(^{ + [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateReady fromOldState:nil callEnterTransition:NO]; + }); + + it(@"should reset the audio stream manger and send an end audio service control frame", ^{ + OCMVerify([mockAudioStreamManager stop]); + OCMVerify([protocolMock endServiceWithType:SDLServiceTypeAudio]); + }); + + context(@"when the end audio service ACKs", ^{ + __block SDLProtocolHeader *testAudioHeader = nil; + __block SDLProtocolMessage *testAudioMessage = nil; + + beforeEach(^{ + testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testAudioHeader.frameType = SDLFrameTypeSingle; + testAudioHeader.frameData = SDLFrameInfoEndServiceACK; + testAudioHeader.encrypted = NO; + testAudioHeader.serviceType = SDLServiceTypeAudio; + testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil]; + + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceACK:testAudioMessage]; + }); + + it(@"should transistion to the stopped state", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped)); + }); + }); + + context(@"when the end audio service NAKs", ^{ + __block SDLProtocolHeader *testAudioHeader = nil; + __block SDLProtocolMessage *testAudioMessage = nil; + + beforeEach(^{ + testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testAudioHeader.frameType = SDLFrameTypeSingle; + testAudioHeader.frameData = SDLFrameInfoEndServiceNACK; + testAudioHeader.encrypted = NO; + testAudioHeader.serviceType = SDLServiceTypeAudio; + testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil]; + + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceNAK:testAudioMessage]; + }); + + it(@"should transistion to the stopped state", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped)); + }); + }); + }); + }); }); QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m index 079945a5f..f138e873d 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m @@ -37,16 +37,20 @@ #import "SDLSystemCapabilityManager.h" #import "SDLV2ProtocolHeader.h" #import "SDLV2ProtocolMessage.h" +#import "SDLVehicleType.h" #import "SDLVideoStreamingCapability.h" #import "SDLVideoStreamingState.h" -#import "TestConnectionManager.h" #import "SDLVehicleType.h" -#import "SDLVersion.h" +#import "TestConnectionManager.h" + @interface SDLStreamingVideoLifecycleManager () + +@property (weak, nonatomic) SDLProtocol *protocol; @property (copy, nonatomic, readonly) NSString *appName; @property (copy, nonatomic, readonly) NSString *videoStreamBackgroundString; -@property (copy, nonatomic) NSString *connectedVehicleMake; +@property (copy, nonatomic, nullable) NSString *connectedVehicleMake; + @end QuickSpecBegin(SDLStreamingVideoLifecycleManagerSpec) @@ -68,8 +72,6 @@ describe(@"the streaming video manager", ^{ hmiStatus.videoStreamingState = streamState; SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:hmiStatus]; [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.3]; }; beforeEach(^{ @@ -82,7 +84,7 @@ describe(@"the streaming video manager", ^{ testLifecycleConfiguration.appType = SDLAppHMITypeNavigation; - testConfig = [SDLConfiguration configurationWithLifecycle:testLifecycleConfiguration lockScreen:SDLLockScreenConfiguration.enabledConfiguration logging:SDLLogConfiguration.debugConfiguration streamingMedia:testConfiguration fileManager:SDLFileManagerConfiguration.defaultConfiguration]; + testConfig = [[SDLConfiguration alloc] initWithLifecycle:testLifecycleConfiguration lockScreen:[SDLLockScreenConfiguration enabledConfiguration] logging:[SDLLogConfiguration debugConfiguration] streamingMedia:testConfiguration fileManager:[SDLFileManagerConfiguration defaultConfiguration] encryption:nil]; testSystemCapabilityManager = OCMClassMock([SDLSystemCapabilityManager class]); streamingLifecycleManager = [[SDLStreamingVideoLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfig systemCapabilityManager:testSystemCapabilityManager]; @@ -179,12 +181,11 @@ describe(@"the streaming video manager", ^{ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:someRegisterAppInterfaceResponse]; [[NSNotificationCenter defaultCenter] postNotification:notification]; - [NSThread sleepForTimeInterval:0.1]; }); it(@"should save the connected vehicle make but not the screen size", ^{ - expect(@(CGSizeEqualToSize(streamingLifecycleManager.videoScaleManager.displayViewportResolution, CGSizeZero))).to(equal(@YES)); - expect(streamingLifecycleManager.connectedVehicleMake).to(equal(testVehicleType.make)); + expect(@(CGSizeEqualToSize(streamingLifecycleManager.videoScaleManager.displayViewportResolution, CGSizeZero))).toEventually(equal(@YES)); + expect(streamingLifecycleManager.connectedVehicleMake).toEventually(equal(testVehicleType.make)); }); }); @@ -204,14 +205,15 @@ describe(@"the streaming video manager", ^{ #pragma clang diagnostic pop someRegisterAppInterfaceResponse.vehicleType = testVehicleType; + someRegisterAppInterfaceResponse.vehicleType = testVehicleType; + SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:someRegisterAppInterfaceResponse]; [[NSNotificationCenter defaultCenter] postNotification:notification]; - [NSThread sleepForTimeInterval:0.1]; }); it(@"should save the connected vehicle make and the screen size", ^{ - expect(@(CGSizeEqualToSize(streamingLifecycleManager.videoScaleManager.displayViewportResolution, CGSizeMake(600, 100)))).to(equal(@YES)); + expect(@(CGSizeEqualToSize(streamingLifecycleManager.videoScaleManager.displayViewportResolution, CGSizeMake(600, 100)))).toEventually(equal(@YES)); expect(streamingLifecycleManager.connectedVehicleMake).toEventually(equal(testVehicleType.make)); }); }); @@ -244,7 +246,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); @@ -254,7 +256,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); @@ -264,7 +266,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateReady)); }); }); @@ -274,7 +276,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateReady)); }); }); @@ -284,7 +286,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); }); @@ -313,7 +315,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the streams", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); @@ -323,7 +325,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); @@ -333,7 +335,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateReady)); }); }); @@ -343,7 +345,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateReady)); }); }); @@ -353,7 +355,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); @@ -364,7 +366,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); @@ -375,7 +377,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should close the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateShuttingDown)); }); }); }); @@ -397,7 +399,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not start the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateStopped)); }); }); @@ -407,7 +409,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not start the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateStopped)); }); }); @@ -417,7 +419,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should start the streams", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateStarting)); }); }); @@ -427,7 +429,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should start the streams", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateStarting)); }); }); @@ -437,7 +439,7 @@ describe(@"the streaming video manager", ^{ }); it(@"should not start the stream", ^{ - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + expect(streamingLifecycleManager.currentVideoStreamState).toEventually(equal(SDLVideoStreamManagerStateStopped)); }); }); }); @@ -550,7 +552,7 @@ describe(@"the streaming video manager", ^{ beforeEach(^{ testVideoStartServicePayload = [[SDLControlFramePayloadVideoStartServiceAck alloc] initWithMTU:testMTU height:testVideoHeight width:testVideoWidth protocol:testVideoProtocol codec:testVideoCodec]; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartServicePayload.data]; - [streamingLifecycleManager handleProtocolStartServiceACKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceACK:testVideoMessage]; }); it(@"should have set all the right properties", ^{ @@ -566,7 +568,7 @@ describe(@"the streaming video manager", ^{ beforeEach(^{ testVideoStartServicePayload = [[SDLControlFramePayloadVideoStartServiceAck alloc] initWithMTU:testMTU height:testVideoHeight width:testVideoWidth protocol:nil codec:nil]; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartServicePayload.data]; - [streamingLifecycleManager handleProtocolStartServiceACKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceACK:testVideoMessage]; }); it(@"should fall back correctly", ^{ @@ -579,7 +581,7 @@ describe(@"the streaming video manager", ^{ context(@"with missing screen height and screen width values", ^{ beforeEach(^{ streamingLifecycleManager.preferredResolutions = @[]; - + testVideoStartServicePayload = [[SDLControlFramePayloadVideoStartServiceAck alloc] initWithMTU:testMTU height:SDLControlFrameInt32NotFound width:SDLControlFrameInt32NotFound protocol:nil codec:nil]; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartServicePayload.data]; expect(@(CGSizeEqualToSize(streamingLifecycleManager.videoScaleManager.displayViewportResolution, CGSizeZero))).to(equal(@YES)); @@ -587,7 +589,7 @@ describe(@"the streaming video manager", ^{ context(@"If no preferred resolutions were set in the data source", ^{ beforeEach(^{ streamingLifecycleManager.dataSource = nil; - [streamingLifecycleManager handleProtocolStartServiceACKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceACK:testVideoMessage]; }); it(@"should not replace the existing screen resolution", ^{ expect(@(CGSizeEqualToSize(streamingLifecycleManager.videoScaleManager.displayViewportResolution, CGSizeZero))).to(beTrue()); @@ -597,14 +599,14 @@ describe(@"the streaming video manager", ^{ context(@"If the preferred resolution was set in the data source", ^{ __block SDLImageResolution *preferredResolutionLow = nil; __block SDLImageResolution *preferredResolutionHigh = nil; - + beforeEach(^{ preferredResolutionLow = [[SDLImageResolution alloc] initWithWidth:10 height:10]; preferredResolutionHigh = [[SDLImageResolution alloc] initWithWidth:100 height:100]; streamingLifecycleManager.dataSource = testDataSource; streamingLifecycleManager.preferredResolutions = @[preferredResolutionLow, preferredResolutionHigh]; - - [streamingLifecycleManager handleProtocolStartServiceACKMessage:testVideoMessage]; + + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceACK:testVideoMessage]; }); it(@"should set the screen size using the first provided preferred resolution", ^{ CGSize preferredFormat = CGSizeMake(preferredResolutionLow.resolutionWidth.floatValue, preferredResolutionLow.resolutionHeight.floatValue); @@ -619,6 +621,8 @@ describe(@"the streaming video manager", ^{ __block SDLProtocolHeader *testVideoHeader = nil; __block SDLProtocolMessage *testVideoMessage = nil; __block SDLControlFramePayloadNak *testVideoStartNakPayload = nil; + __block NSArray<SDLVideoStreamingFormat *> *testPreferredFormats = nil; + __block NSArray<SDLImageResolution *> *testPreferredResolutions = nil; beforeEach(^{ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStarting fromOldState:nil callEnterTransition:NO]; @@ -630,11 +634,21 @@ describe(@"the streaming video manager", ^{ testVideoHeader.serviceType = SDLServiceTypeVideo; }); - context(@"with data", ^{ + context(@"with rejected parameters for resolution and codec and there is more than one supported resolution and video codec", ^{ beforeEach(^{ + SDLVideoStreamingFormat *testVideoFormat = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecTheora protocol:SDLVideoStreamingProtocolWebM]; + SDLVideoStreamingFormat *testVideoFormat2 = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP]; + testPreferredFormats = @[testVideoFormat, testVideoFormat2]; + streamingLifecycleManager.preferredFormats = testPreferredFormats; + + SDLImageResolution *testImageResolution = [[SDLImageResolution alloc] initWithWidth:400 height:200]; + SDLImageResolution *testImageResolution2 = [[SDLImageResolution alloc] initWithWidth:500 height:800]; + testPreferredResolutions = @[testImageResolution, testImageResolution2]; + streamingLifecycleManager.preferredResolutions = testPreferredResolutions; + testVideoStartNakPayload = [[SDLControlFramePayloadNak alloc] initWithRejectedParams:@[[NSString stringWithUTF8String:SDLControlFrameHeightKey], [NSString stringWithUTF8String:SDLControlFrameVideoCodecKey]]]; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartNakPayload.data]; - [streamingLifecycleManager handleProtocolStartServiceNAKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceNAK:testVideoMessage]; }); it(@"should have retried with new properties", ^{ @@ -643,11 +657,56 @@ describe(@"the streaming video manager", ^{ }); }); + context(@"with rejected parameters for codec and there is more than one supported video codec", ^{ + beforeEach(^{ + SDLVideoStreamingFormat *testVideoFormat = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecTheora protocol:SDLVideoStreamingProtocolWebM]; + SDLVideoStreamingFormat *testVideoFormat2 = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP]; + testPreferredFormats = @[testVideoFormat, testVideoFormat2]; + streamingLifecycleManager.preferredFormats = testPreferredFormats; + + SDLImageResolution *testImageResolution = [[SDLImageResolution alloc] initWithWidth:400 height:200]; + testPreferredResolutions = @[testImageResolution]; + streamingLifecycleManager.preferredResolutions = testPreferredResolutions; + + testVideoStartNakPayload = [[SDLControlFramePayloadNak alloc] initWithRejectedParams:@[[NSString stringWithUTF8String:SDLControlFrameVideoCodecKey]]]; + testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartNakPayload.data]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceNAK:testVideoMessage]; + }); + + it(@"should have retried with new properties", ^{ + expect(streamingLifecycleManager.preferredResolutionIndex).to(equal(0)); + expect(streamingLifecycleManager.preferredFormatIndex).to(equal(1)); + }); + }); + + context(@"with rejected parameters for codec and there are no more supported video codecs", ^{ + beforeEach(^{ + SDLVideoStreamingFormat *testVideoFormat = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP]; + testPreferredFormats = @[testVideoFormat]; + streamingLifecycleManager.preferredFormats = testPreferredFormats; + + SDLImageResolution *testImageResolution = [[SDLImageResolution alloc] initWithWidth:400 height:200]; + testPreferredResolutions = @[testImageResolution]; + streamingLifecycleManager.preferredResolutions = testPreferredResolutions; + + testVideoStartNakPayload = [[SDLControlFramePayloadNak alloc] initWithRejectedParams:@[[NSString stringWithUTF8String:SDLControlFrameVideoCodecKey]]]; + testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartNakPayload.data]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceNAK:testVideoMessage]; + }); + + it(@"should end the service", ^{ + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + }); + }); + context(@"with missing data", ^{ beforeEach(^{ + streamingLifecycleManager.preferredFormats = testPreferredFormats; + streamingLifecycleManager.preferredResolutions = testPreferredResolutions; + testVideoStartNakPayload = [[SDLControlFramePayloadNak alloc] initWithRejectedParams:nil]; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:testVideoStartNakPayload.data]; - [streamingLifecycleManager handleProtocolStartServiceNAKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceNAK:testVideoMessage]; }); it(@"should end the service", ^{ @@ -670,7 +729,7 @@ describe(@"the streaming video manager", ^{ testVideoHeader.serviceType = SDLServiceTypeVideo; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:nil]; - [streamingLifecycleManager handleProtocolEndServiceACKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceACK:testVideoMessage]; }); it(@"should have set all the right properties", ^{ @@ -692,7 +751,7 @@ describe(@"the streaming video manager", ^{ testVideoHeader.serviceType = SDLServiceTypeVideo; testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:nil]; - [streamingLifecycleManager handleProtocolEndServiceNAKMessage:testVideoMessage]; + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceNAK:testVideoMessage]; }); it(@"should have set all the right properties", ^{ @@ -702,6 +761,112 @@ describe(@"the streaming video manager", ^{ }); }); + describe(@"stopping the manager", ^{ + __block BOOL handlerCalled = NO; + + beforeEach(^{ + handlerCalled = NO; + [streamingLifecycleManager endVideoServiceWithCompletionHandler:^ { + handlerCalled = YES; + }]; + streamingLifecycleManager.connectedVehicleMake = @"OEM_make_2"; + }); + + context(@"when the manager is not stopped", ^{ + beforeEach(^{ + [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateReady fromOldState:nil callEnterTransition:NO]; + [streamingLifecycleManager stop]; + }); + + it(@"should transition to the stopped state", ^{ + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + expect(streamingLifecycleManager.protocol).to(beNil()); + expect(streamingLifecycleManager.connectedVehicleMake).to(beNil()); + expect(streamingLifecycleManager.hmiLevel).to(equal(SDLHMILevelNone)); + expect(streamingLifecycleManager.videoStreamingState).to(equal(SDLVideoStreamingStateNotStreamable)); + expect(streamingLifecycleManager.preferredFormatIndex).to(equal(0)); + expect(streamingLifecycleManager.preferredResolutionIndex).to(equal(0)); + expect(handlerCalled).to(beTrue()); + }); + }); + + context(@"when the manager is already stopped", ^{ + beforeEach(^{ + [streamingLifecycleManager.videoStreamStateMachine setToState:SDLAudioStreamManagerStateStopped fromOldState:nil callEnterTransition:NO]; + [streamingLifecycleManager stop]; + }); + + it(@"should stay in the stopped state", ^{ + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + expect(streamingLifecycleManager.protocol).to(beNil()); + expect(streamingLifecycleManager.connectedVehicleMake).to(beNil()); + expect(streamingLifecycleManager.hmiLevel).to(equal(SDLHMILevelNone)); + expect(streamingLifecycleManager.videoStreamingState).to(equal(SDLVideoStreamingStateNotStreamable)); + expect(streamingLifecycleManager.preferredFormatIndex).to(equal(0)); + expect(streamingLifecycleManager.preferredResolutionIndex).to(equal(0)); + expect(handlerCalled).to(beFalse()); + }); + }); + }); + + describe(@"starting the manager", ^{ + __block SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]); + + beforeEach(^{ + [streamingLifecycleManager startWithProtocol:protocolMock]; + }); + + describe(@"then ending the video service through the secondary transport", ^{ + beforeEach(^{ + [streamingLifecycleManager endVideoServiceWithCompletionHandler:^{}]; + }); + + it(@"should send an end video service control frame", ^{ + OCMVerify([protocolMock endServiceWithType:SDLServiceTypeVideo]); + }); + + context(@"when the end video service ACKs", ^{ + __block SDLProtocolHeader *testVideoHeader = nil; + __block SDLProtocolMessage *testVideoMessage = nil; + + beforeEach(^{ + testVideoHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testVideoHeader.frameType = SDLFrameTypeSingle; + testVideoHeader.frameData = SDLFrameInfoEndServiceACK; + testVideoHeader.encrypted = NO; + testVideoHeader.serviceType = SDLServiceTypeVideo; + testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:nil]; + + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceACK:testVideoMessage]; + }); + + it(@"should transistion to the stopped state", ^{ + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + }); + }); + + context(@"when the end audio service NAKs", ^{ + __block SDLProtocolHeader *testVideoHeader = nil; + __block SDLProtocolMessage *testVideoMessage = nil; + + beforeEach(^{ + testVideoHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testVideoHeader.frameType = SDLFrameTypeSingle; + testVideoHeader.frameData = SDLFrameInfoEndServiceNACK; + testVideoHeader.encrypted = NO; + testVideoHeader.serviceType = SDLServiceTypeVideo; + testVideoMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testVideoHeader andPayload:nil]; + + [streamingLifecycleManager protocol:protocolMock didReceiveEndServiceNAK:testVideoMessage]; + }); + + it(@"should transistion to the stopped state", ^{ + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped)); + }); + }); + }); + }); + describe(@"Creating a background video stream string", ^{ __block NSString *expectedVideoStreamBackgroundString = [NSString stringWithFormat:@"When it is safe to do so, open %@ on your phone", testAppName]; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m index fb7298988..99aa9dbb5 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m @@ -6,6 +6,7 @@ #import "SDLFileManager.h" #import "SDLHMILevel.h" #import "SDLImage.h" +#import "SDLImageField.h" #import "SDLMetadataTags.h" #import "SDLPutFileResponse.h" #import "SDLShow.h" @@ -37,6 +38,8 @@ @property (assign, nonatomic) BOOL isDirty; +- (void)sdl_displayCapabilityDidUpdate:(SDLSystemCapability *)systemCapability; + @end QuickSpecBegin(SDLTextAndGraphicManagerSpec) @@ -375,7 +378,7 @@ describe(@"text and graphic manager", ^{ testManager.windowCapability = [[SDLWindowCapability alloc] init]; }); - it(@"should send everything", ^{ + it(@"should send nothing", ^{ testManager.mediaTrackTextField = textMediaTrack; testManager.title = textTitle; testManager.textField1 = textLine1; @@ -386,12 +389,12 @@ describe(@"text and graphic manager", ^{ testManager.batchUpdates = NO; [testManager updateWithCompletionHandler:nil]; - expect(testManager.inProgressUpdate.mediaTrack).to(equal(textMediaTrack)); - expect(testManager.inProgressUpdate.templateTitle).to(equal(textTitle)); - expect(testManager.inProgressUpdate.mainField1).to(equal(textLine1)); - expect(testManager.inProgressUpdate.mainField2).to(equal(textLine2)); - expect(testManager.inProgressUpdate.mainField3).to(equal(textLine3)); - expect(testManager.inProgressUpdate.mainField4).to(equal(textLine4)); + expect(testManager.inProgressUpdate.mediaTrack).toNot(equal(textMediaTrack)); + expect(testManager.inProgressUpdate.templateTitle).toNot(equal(textTitle)); + expect(testManager.inProgressUpdate.mainField1).toNot(equal(textLine1)); + expect(testManager.inProgressUpdate.mainField2).toNot(equal(textLine2)); + expect(testManager.inProgressUpdate.mainField3).toNot(equal(textLine3)); + expect(testManager.inProgressUpdate.mainField4).toNot(equal(textLine4)); }); }); @@ -863,10 +866,38 @@ describe(@"text and graphic manager", ^{ __block NSString *testTextFieldText = @"mainFieldText"; beforeEach(^{ + testManager.windowCapability = [[SDLWindowCapability alloc] init]; + SDLImageField *primaryImageField = [[SDLImageField alloc] init]; + primaryImageField.name = SDLImageFieldNameGraphic; + SDLImageField *secondaryImageField = [[SDLImageField alloc] init]; + secondaryImageField.name = SDLImageFieldNameSecondaryGraphic; + testManager.windowCapability.imageFields = @[primaryImageField, secondaryImageField]; + + SDLTextField *lineOneField = [[SDLTextField alloc] init]; + lineOneField.name = SDLTextFieldNameMainField1; + testManager.windowCapability.textFields = @[lineOneField]; + testManager.batchUpdates = YES; testManager.textField1 = testTextFieldText; }); + context(@"when imageFields are nil", ^{ + beforeEach(^{ + testManager.windowCapability.imageFields = nil; + }); + + it(@"should send nothing", ^{ + testManager.primaryGraphic = testArtwork; + testManager.secondaryGraphic = testArtwork; + testManager.batchUpdates = NO; + [testManager updateWithCompletionHandler:nil]; + + expect(testManager.inProgressUpdate.graphic).to(beNil()); + expect(testManager.inProgressUpdate.secondaryGraphic).to(beNil()); + expect(testManager.inProgressUpdate.mainField1).to(equal(testTextFieldText)); + }); + }); + context(@"when the image is already on the head unit", ^{ beforeEach(^{ OCMStub([mockFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(YES); @@ -882,23 +913,6 @@ describe(@"text and graphic manager", ^{ expect(testManager.inProgressUpdate.secondaryGraphic.value).to(equal(testArtworkName)); expect(testManager.inProgressUpdate.mainField1).to(equal(testTextFieldText)); }); - - context(@"when imageFields are nil", ^{ - beforeEach(^{ - testManager.windowCapability = [[SDLWindowCapability alloc] init]; - }); - - it(@"should send everything", ^{ - testManager.primaryGraphic = testArtwork; - testManager.secondaryGraphic = testArtwork; - testManager.batchUpdates = NO; - [testManager updateWithCompletionHandler:nil]; - - expect(testManager.inProgressUpdate.graphic.value).to(equal(testArtworkName)); - expect(testManager.inProgressUpdate.secondaryGraphic.value).to(equal(testArtworkName)); - expect(testManager.inProgressUpdate.mainField1).to(equal(testTextFieldText)); - }); - }); }); context(@"when the image is a static icon", ^{ diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLUploadFileOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLUploadFileOperationSpec.m index 93254ca78..570d2bd9e 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLUploadFileOperationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLUploadFileOperationSpec.m @@ -31,7 +31,7 @@ expect(putFile.offset).to(equal(@(index * mtuSize))); expect(putFile.persistentFile).to(equal(@NO)); - expect(putFile.syncFileName).to(equal(testFile.name)); + expect(putFile.sdlFileName).to(equal(testFile.name)); expect(putFile.bulkData).to(equal(testBulkFileData)); expect(putFile.crc).to(equal([NSNumber numberWithUnsignedLong:testBulkFileDataCrc])); diff --git a/SmartDeviceLinkTests/DevAPISpecs/TestOldConfigurationUpdateManagerDelegate.h b/SmartDeviceLinkTests/DevAPISpecs/TestOldConfigurationUpdateManagerDelegate.h new file mode 100644 index 000000000..f527decea --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/TestOldConfigurationUpdateManagerDelegate.h @@ -0,0 +1,19 @@ +// +// TestOldConfigurationUpdateManagerDelegate.h +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/4/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#import "SDLManagerDelegate.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TestOldConfigurationUpdateManagerDelegate : NSObject <SDLManagerDelegate> + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLinkTests/DevAPISpecs/TestOldConfigurationUpdateManagerDelegate.m b/SmartDeviceLinkTests/DevAPISpecs/TestOldConfigurationUpdateManagerDelegate.m new file mode 100644 index 000000000..765df8172 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/TestOldConfigurationUpdateManagerDelegate.m @@ -0,0 +1,24 @@ +// +// TestOldConfigurationUpdateManagerDelegate.m +// SmartDeviceLinkTests +// +// Created by Joel Fischer on 6/4/20. +// Copyright © 2020 smartdevicelink. All rights reserved. +// + +#import "TestOldConfigurationUpdateManagerDelegate.h" + +@implementation TestOldConfigurationUpdateManagerDelegate + +- (void)hmiLevel:(nonnull SDLHMILevel)oldLevel didChangeToLevel:(nonnull SDLHMILevel)newLevel { } + +- (void)managerDidDisconnect { } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (nullable SDLLifecycleConfigurationUpdate *)managerShouldUpdateLifecycleToLanguage:(SDLLanguage)language { + return nil; +} +#pragma mark diagnostic pop + +@end |