diff options
author | leonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com> | 2020-12-23 04:34:41 +0200 |
---|---|---|
committer | leonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com> | 2020-12-23 04:34:41 +0200 |
commit | 638dacb4ea41228ddbb669f7146deec755f6c388 (patch) | |
tree | 6fb2d23435575ef04cd13e93ab98a38f6523e210 | |
parent | df0747d1b6822e5948c6ef60f823ac8b8e980422 (diff) | |
download | sdl_ios-638dacb4ea41228ddbb669f7146deec755f6c388.tar.gz |
[0296] 'upd video stream cap': revert unnecessary changes, update test cases.
11 files changed, 382 insertions, 113 deletions
diff --git a/SmartDeviceLink/private/NSMapTable+Subscripting.h b/SmartDeviceLink/private/NSMapTable+Subscripting.h index b3b519803..313e25be4 100644 --- a/SmartDeviceLink/private/NSMapTable+Subscripting.h +++ b/SmartDeviceLink/private/NSMapTable+Subscripting.h @@ -13,12 +13,11 @@ NS_ASSUME_NONNULL_BEGIN /** * Implement subscripting methods for NSMapTable to allow for easily pushing and pulling objects. */ -@interface NSMapTable<KeyType, ObjectType> (Subscripting) +@interface NSMapTable (Subscripting) -- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType<NSCopying>)key; -- (nullable ObjectType)objectForKeyedSubscript:(KeyType<NSCopying>)key; -@property (readonly, copy) NSArray<KeyType> *allKeys; +- (void)setObject:(nullable id)anObject forKeyedSubscript:(id<NSCopying>)key; +- (nullable id)objectForKeyedSubscript:(id<NSCopying>)key; @end -NS_ASSUME_NONNULL_END +NS_ASSUME_NONNULL_END
\ No newline at end of file diff --git a/SmartDeviceLink/private/NSMapTable+Subscripting.m b/SmartDeviceLink/private/NSMapTable+Subscripting.m index 041b90f57..3ac063f62 100644 --- a/SmartDeviceLink/private/NSMapTable+Subscripting.m +++ b/SmartDeviceLink/private/NSMapTable+Subscripting.m @@ -20,10 +20,6 @@ NS_ASSUME_NONNULL_BEGIN return [self objectForKey:key]; } -- (NSArray *)allKeys { - return self.dictionaryRepresentation.allKeys; -} - @end -NS_ASSUME_NONNULL_END +NS_ASSUME_NONNULL_END
\ No newline at end of file diff --git a/SmartDeviceLink/private/NSMutableDictionary+Store.m b/SmartDeviceLink/private/NSMutableDictionary+Store.m index 227412521..c1a81363b 100644 --- a/SmartDeviceLink/private/NSMutableDictionary+Store.m +++ b/SmartDeviceLink/private/NSMutableDictionary+Store.m @@ -9,7 +9,6 @@ #import "NSMutableDictionary+Store.h" #import "SDLRPCStruct.h" #import "SDLError.h" -#import "SDLLogMacros.h" NS_ASSUME_NONNULL_BEGIN @@ -42,46 +41,27 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - object - (nullable id)sdl_objectForName:(SDLRPCParameterName)name ofClass:(Class)classType error:(NSError * _Nullable __autoreleasing * _Nullable)error { - if (error) { - // reset any error - *error = NULL; - } id obj = [self sdl_objectForName:name]; - if (!obj) { - return nil; - } - if ([obj isKindOfClass:NSNull.class]) { - SDLLogD(@"NSNull, it must be a mistake"); - } - if ([obj isKindOfClass:classType]) { + if (obj == nil || [obj isKindOfClass:classType]) { return obj; - } - // translate dictionaries to objects - if ([obj isKindOfClass:NSDictionary.class] && [classType instancesRespondToSelector:@selector(initWithDictionary:)]) { + } else if ([obj isKindOfClass:NSDictionary.class] && [classType instancesRespondToSelector:@selector(initWithDictionary:)]) { obj = [[classType alloc] initWithDictionary:(NSDictionary *)obj]; // update store so that the object isn't created multiple times [self sdl_setObject:obj forName:name]; return obj; - } - - if ((classType == NSString.class) && [obj respondsToSelector:@selector(stringValue)]) { - // fix an issue when JSON treats number values as NSNumber and a string expected - NSString *numString = [obj stringValue]; - if (numString) { - return numString; - } - } - // The object in the store is not correct, we'll assert in debug and return an error and nil - NSError *wrongObjectError = [NSError sdl_rpcStore_invalidObjectErrorWithObject:obj expectedType:classType]; + } else { + // The object in the store is not correct, we'll assert in debug and return an error and nil + NSError *wrongObjectError = [NSError sdl_rpcStore_invalidObjectErrorWithObject:obj expectedType:classType]; - SDLLogAssert(@"Retrieving object from store error: %@, for object key: \"%@\", in dictionary: %@", wrongObjectError.localizedFailureReason, name, self); + SDLLogAssert(@"Retrieving object from store error: %@, for object key: \"%@\", in dictionary: %@", wrongObjectError.localizedFailureReason, name, self); - if (error) { - *error = wrongObjectError; + if (error) { + *error = wrongObjectError; + } + return nil; } - return nil; } #pragma mark - objects diff --git a/SmartDeviceLink/private/SDLCarWindow.m b/SmartDeviceLink/private/SDLCarWindow.m index b9637ee07..48f06ddd7 100644 --- a/SmartDeviceLink/private/SDLCarWindow.m +++ b/SmartDeviceLink/private/SDLCarWindow.m @@ -50,17 +50,14 @@ NS_ASSUME_NONNULL_BEGIN _renderingType = configuration.carWindowRenderingType; _allowMultipleOrientations = configuration.allowMultipleViewControllerOrientations; - //Note: the notification center can or should be local, not default - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter addObserver:self selector:@selector(sdl_didReceiveVideoStreamStarted:) name:SDLVideoStreamDidStartNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(sdl_didReceiveVideoStreamStopped:) name:SDLVideoStreamDidStopNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(sdl_didReceiveVideoStreamSuspended:) name:SDLVideoStreamSuspendedNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveVideoStreamStarted:) name:SDLVideoStreamDidStartNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveVideoStreamStopped:) name:SDLVideoStreamDidStopNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_willPresentLockScreenViewController:) name:SDLLockScreenManagerWillPresentLockScreenViewController object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_willDismissLockScreenViewController:) name:SDLLockScreenManagerWillDismissLockScreenViewController object:nil]; - [notificationCenter addObserver:self selector:@selector(sdl_willPresentLockScreenViewController:) name:SDLLockScreenManagerWillPresentLockScreenViewController object:nil]; - [notificationCenter addObserver:self selector:@selector(sdl_willDismissLockScreenViewController:) name:SDLLockScreenManagerWillDismissLockScreenViewController object:nil]; - [notificationCenter addObserver:self selector:@selector(sdl_didPresentLockScreenViewController:) name:SDLLockScreenManagerDidPresentLockScreenViewController object:nil]; - [notificationCenter addObserver:self selector:@selector(sdl_didDismissLockScreenViewController:) name:SDLLockScreenManagerDidDismissLockScreenViewController object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didPresentLockScreenViewController:) name:SDLLockScreenManagerDidPresentLockScreenViewController object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didDismissLockScreenViewController:) name:SDLLockScreenManagerDidDismissLockScreenViewController object:nil]; return self; } @@ -81,12 +78,10 @@ NS_ASSUME_NONNULL_BEGIN return; } - UIGraphicsBeginImageContextWithOptions(bounds.size, YES, 1); - CGContextRef context = UIGraphicsGetCurrentContext(); - + UIGraphicsBeginImageContextWithOptions(bounds.size, YES, 1.0f); switch (self.renderingType) { case SDLCarWindowRenderingTypeLayer: { - [self.rootViewController.view.layer renderInContext:context]; + [self.rootViewController.view.layer renderInContext:UIGraphicsGetCurrentContext()]; } break; case SDLCarWindowRenderingTypeViewAfterScreenUpdates: { [self.rootViewController.view drawViewHierarchyInRect:bounds afterScreenUpdates:YES]; @@ -100,11 +95,12 @@ NS_ASSUME_NONNULL_BEGIN UIGraphicsEndImageContext(); CGImageRef imageRef = screenshot.CGImage; - CVPixelBufferRef pixelBuffer = imageRef ? [self.class sdl_createPixelBufferForImageRef:imageRef usingPool:self.streamManager.pixelBufferPool] : nil; + CVPixelBufferRef pixelBuffer = [self.class sdl_createPixelBufferForImageRef:imageRef usingPool:self.streamManager.pixelBufferPool]; if (pixelBuffer != nil) { - const BOOL success = [self.streamManager sendVideoData:pixelBuffer]; + BOOL success = [self.streamManager sendVideoData:pixelBuffer]; if (!success) { SDLLogE(@"Video frame will not be sent because the video frame encoding failed"); + return; } CVPixelBufferRelease(pixelBuffer); } else { @@ -113,17 +109,10 @@ NS_ASSUME_NONNULL_BEGIN } - (void)updateVdeoStreamingCapability:(SDLVideoStreamingCapability *)videoStreamingCapability { - [self sdl_applyDisplayDimensionsToViewController:self.rootViewController]; + [self sdl_applyDisplayDimensionsToRootViewController:self.rootViewController]; } - (void)dealloc { - [self unsubscribeFromNotifications]; -} - -#pragma mark - Notifications - -- (void)unsubscribeFromNotifications { - //Note: use a proper center [[NSNotificationCenter defaultCenter] removeObserver:self]; } @@ -151,7 +140,7 @@ NS_ASSUME_NONNULL_BEGIN SDLLogD(@"Video stream started"); dispatch_async(dispatch_get_main_queue(), ^{ - [self sdl_applyDisplayDimensionsToViewController:self.rootViewController]; + [self sdl_applyDisplayDimensionsToRootViewController:self.rootViewController]; }); } @@ -160,18 +149,11 @@ NS_ASSUME_NONNULL_BEGIN dispatch_async(dispatch_get_main_queue(), ^{ // And also reset the streamingViewController's frame, because we are about to show it. - UIViewController *viewController = self.rootViewController; - const CGRect frame = [UIScreen mainScreen].bounds; - viewController.view.frame = frame; - viewController.view.bounds = frame; - + self.rootViewController.view.frame = [UIScreen mainScreen].bounds; SDLLogD(@"Video stream ended, setting view controller frame back: %@", NSStringFromCGRect(self.rootViewController.view.frame)); }); } -- (void)sdl_didReceiveVideoStreamSuspended:(NSNotification *)notification { -} - #pragma mark - Custom Accessors - (void)setRootViewController:(nullable UIViewController *)rootViewController { dispatch_async(dispatch_get_main_queue(), ^{ @@ -187,16 +169,16 @@ NS_ASSUME_NONNULL_BEGIN @throw [NSException sdl_carWindowOrientationException]; } - [self sdl_applyDisplayDimensionsToViewController:rootViewController]; + [self sdl_applyDisplayDimensionsToRootViewController:rootViewController]; self->_rootViewController = rootViewController; }); } #pragma mark - Private Helpers -// memory management 'create': release the result object when done +// memory management 'create': release the result object when done (create* - follow the naming convention) + (nullable CVPixelBufferRef)sdl_createPixelBufferForImageRef:(CGImageRef)imageRef usingPool:(CVPixelBufferPoolRef)pool { - const size_t imageWidth = CGImageGetWidth(imageRef); - const size_t imageHeight = CGImageGetHeight(imageRef); + size_t imageWidth = CGImageGetWidth(imageRef); + size_t imageHeight = CGImageGetHeight(imageRef); CVPixelBufferRef pixelBuffer; CVReturn result = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer); @@ -217,13 +199,12 @@ NS_ASSUME_NONNULL_BEGIN return pixelBuffer; } - /** - Sets the viewController frame to the display viewport dimensions. + Sets the rootViewController's frame to the display's viewport dimensions. - @param viewController (aka rootViewController) The view controller to resize + @param rootViewController The view controller to resize */ -- (void)sdl_applyDisplayDimensionsToViewController:(UIViewController *)viewController { +- (void)sdl_applyDisplayDimensionsToRootViewController:(UIViewController *)rootViewController { const CGSize displSize = self.streamManager.videoScaleManager.displayViewportResolution; if (1 > displSize.width) { // The dimensions of the display screen is unknown because the connected head unit did not provide a screen resolution in the `RegisterAppInterfaceResponse` or in the video start service ACK. @@ -232,8 +213,8 @@ NS_ASSUME_NONNULL_BEGIN } const CGRect appFrame = self.streamManager.videoScaleManager.appViewportFrame; - viewController.view.frame = appFrame; - viewController.view.bounds = appFrame; + rootViewController.view.frame = appFrame; + rootViewController.view.bounds = appFrame; SDLLogD(@"Setting CarWindow frame to: %@ (display size: %@)", NSStringFromCGSize(appFrame.size), NSStringFromCGSize(displSize)); } diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m index 32d2cfcbf..21aeaf15d 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m @@ -21,6 +21,7 @@ #import "SDLLockScreenManager.h" #import "SDLLogConfiguration.h" #import "SDLManagerDelegate.h" +#import "SDLMsgVersion.h" #import "SDLNotificationDispatcher.h" #import "SDLOnAppInterfaceUnregistered.h" #import "SDLOnAppServiceData.h" @@ -62,6 +63,19 @@ @property (strong, nonatomic, nullable) SDLSecondaryTransportManager *secondaryTransportManager; @property (strong, nonatomic) SDLEncryptionLifecycleManager *encryptionLifecycleManager; @property (strong, nonatomic, nullable) SDLLifecycleProtocolHandler *protocolHandler; +- (void)didEnterStateConnected; +@end + +@interface SDLLifecycleTestManager : SDLLifecycleManager +- (void)sendConnectionManagerRequest:(__kindof SDLRPCMessage *)request withResponseHandler:(nullable SDLResponseHandler)handler; +@property (strong, nonatomic, nullable) __kindof SDLRPCMessage *testRequest; +@end + +@implementation SDLLifecycleTestManager +// override parent method +- (void)sendConnectionManagerRequest:(__kindof SDLRPCMessage *)request withResponseHandler:(nullable SDLResponseHandler)handler { + self.testRequest = request; +} @end @interface SDLGlobals () @@ -88,6 +102,29 @@ QuickConfigurationEnd QuickSpecBegin(SDLLifecycleManagerSpec) +describe(@"test lifecycle manager internals", ^{ + // note: this test was created to satisfy Cocodev + context(@"init and assign version", ^{ + SDLLifecycleTestManager *manager = [[SDLLifecycleTestManager alloc] init]; + it(@"expect object to be created", ^{ + expect(manager).notTo(beNil()); + }); + const UInt8 majorVersion = 9; + const UInt8 minorVersion = 8; + const UInt8 patchVersion = 7; + SDLMsgVersion *expectedVersion = [[SDLMsgVersion alloc] initWithMajorVersion:majorVersion minorVersion:minorVersion patchVersion:patchVersion]; + manager.sdlMsgVersionString = [NSString stringWithFormat:@"%d.%d.%d", (int)majorVersion, (int)minorVersion, (int)patchVersion]; + context(@"didEnterStateConnected", ^{ + [manager didEnterStateConnected]; + it(@"expect request to be of proper kind and with a proper version", ^{ + expect([manager.testRequest isKindOfClass:SDLRegisterAppInterface.class]).to(equal(YES)); + SDLRegisterAppInterface *regRequest = manager.testRequest; + expect([regRequest.sdlMsgVersion isEqual:expectedVersion]).to(equal(YES)); + }); + }); + }); +}); + describe(@"a lifecycle manager", ^{ __block SDLLifecycleManager *testManager = nil; __block SDLConfiguration *testConfig = nil; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m index cc68b388c..d17342e4d 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m @@ -17,6 +17,7 @@ #import "SDLGetSystemCapabilityResponse.h" #import "SDLGenericResponse.h" #import "SDLGlobals.h" +#import "SDLH264VideoEncoder.h" #import "SDLHMICapabilities.h" #import "SDLHMILevel.h" #import "SDLImageResolution.h" @@ -57,12 +58,66 @@ @property (copy, nonatomic, nullable) NSString *connectedVehicleMake; @property (strong, nonatomic, nullable) SDLSupportedStreamingRange *supportedLandscapeStreamingRange; @property (strong, nonatomic, nullable) SDLSupportedStreamingRange *supportedPortraitStreamingRange; +@property (weak, nonatomic, nullable) id<SDLStreamingMediaDelegate> delegate; +@property (assign, nonatomic) BOOL shouldAutoResume; +@property (strong, nonatomic, nullable) SDLVideoStreamingCapability *videoStreamingCapability; +@property (strong, nonatomic, nullable) SDLVideoStreamingCapability *videoStreamingCapabilityUpdated; +@property (strong, nonatomic, nullable) CADisplayLink *displayLink; - (void)shutDown; - (NSArray<SDLVideoStreamingCapability *>* __nullable)matchVideoCapability:(SDLVideoStreamingCapability *)videoStreamingCapability; +- (void)suspendVideo; +- (void)didEnterStateVideoStreamStopped; +- (void)didEnterStateVideoStreamStarting; +- (void)didEnterStateVideoStreamReady; +- (void)didEnterStateVideoStreamSuspended; +- (void)sdl_displayCapabilityDidUpdate:(SDLSystemCapability *)systemCapability; @end +@interface SDLStreamingVideoLifecycleTestManager : SDLStreamingVideoLifecycleManager +@property (assign) BOOL didStopVideoSession; +@property (strong, nullable) id testVideoCapabilityUpdatedWhileStarting; +@property (strong, nullable) id testVideoCapabilityUpdatedWhenStreaming; +@end + +@implementation SDLStreamingVideoLifecycleTestManager + +- (BOOL)isVideoConnected { + return NO; +} + +- (void)sdl_stopVideoSession { + self.didStopVideoSession = YES; +} + +- (void)sdl_applyVideoCapabilityWhileStarting:(SDLVideoStreamingCapability *)videoCapabilityUpdated { + self.testVideoCapabilityUpdatedWhileStarting = videoCapabilityUpdated; +} + +- (void)sdl_applyVideoCapabilityWhenStreaming:(nullable SDLVideoStreamingCapability *)videoCapability { + self.testVideoCapabilityUpdatedWhenStreaming = videoCapability; +} + +- (BOOL)isAppStateVideoStreamCapable { + return YES; +} + +- (SDLVideoStreamingFormat *)videoFormat { + return [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW]; +} + +- (SDLH264VideoEncoder *)videoEncoder { + return OCMClassMock([SDLH264VideoEncoder class]); +} + +- (BOOL)useDisplayLink { + return YES; +} + +@end + + // expose private methods to the test suite @interface SDLVideoStreamingCapability (test) - (NSArray <SDLVideoStreamingCapability*>*)allVideoStreamingCapabilitiesPlain; @@ -181,6 +236,163 @@ QuickSpecEnd QuickSpecBegin(SDLStreamingVideoLifecycleManagerSpec_Runtime) +describe(@"test internals", ^{ + // note: this test suite created to satisfy Cocodev + context(@"init extended manager", ^{ + id<SDLConnectionManagerType> mockConnectionManager = OCMProtocolMock(@protocol(SDLConnectionManagerType)); + SDLConfiguration *configuration = [[SDLConfiguration alloc] init]; + SDLStreamingVideoLifecycleTestManager *streamingLifecycleManager = [[SDLStreamingVideoLifecycleTestManager alloc] initWithConnectionManager:mockConnectionManager configuration:configuration systemCapabilityManager:nil]; + SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]); + it(@"suspendVideo with and without a protocol", ^{ + expect(streamingLifecycleManager.didStopVideoSession).to(equal(NO)); + [streamingLifecycleManager suspendVideo]; + expect(streamingLifecycleManager.didStopVideoSession).to(equal(NO)); + streamingLifecycleManager.protocol = protocolMock; + [streamingLifecycleManager suspendVideo]; + expect(streamingLifecycleManager.didStopVideoSession).to(equal(YES)); + }); + + context(@"test delegate", ^{ + TestStreamingMediaDelegate *delegate = [[TestStreamingMediaDelegate alloc] init]; + streamingLifecycleManager.delegate = delegate; + it(@"expect delegate to be stopped in time", ^{ + expect(delegate.isStopped).to(equal(NO)); + [streamingLifecycleManager didEnterStateVideoStreamStopped]; + expect(delegate.isStopped).toEventually(equal(YES)); + }); + }); + }); + + context(@"init extended manager", ^{ + id<SDLConnectionManagerType> mockConnectionManager = OCMProtocolMock(@protocol(SDLConnectionManagerType)); + SDLConfiguration *configuration = [[SDLConfiguration alloc] init]; + SDLStreamingVideoLifecycleTestManager *streamingLifecycleManager = [[SDLStreamingVideoLifecycleTestManager alloc] initWithConnectionManager:mockConnectionManager configuration:configuration systemCapabilityManager:nil]; + + context(@"test didEnterStateVideoStreamStopped", ^{ + streamingLifecycleManager.shouldAutoResume = YES; + it(@"state before and after", ^{ + SDLState *stateBefore = streamingLifecycleManager.videoStreamStateMachine.currentState; + [streamingLifecycleManager didEnterStateVideoStreamStopped]; + SDLState *stateAfter = streamingLifecycleManager.videoStreamStateMachine.currentState; + + expect([stateBefore isEqualToString:SDLVideoStreamManagerStateStopped]).to(equal(YES)); + expect([stateAfter isEqualToString:SDLVideoStreamManagerStateStarting]).to(equal(YES)); + }); + }); + }); + + context(@"init extended manager", ^{ + id<SDLConnectionManagerType> mockConnectionManager = OCMProtocolMock(@protocol(SDLConnectionManagerType)); + SDLConfiguration *configuration = [[SDLConfiguration alloc] init]; + SDLStreamingVideoLifecycleTestManager *streamingLifecycleManager = [[SDLStreamingVideoLifecycleTestManager alloc] initWithConnectionManager:mockConnectionManager configuration:configuration systemCapabilityManager:nil]; + + context(@"test videoStreamingCapabilityUpdated", ^{ + streamingLifecycleManager.shouldAutoResume = YES; + SDLVideoStreamingCapability *videoStreamingCapabilityUpdated = OCMClassMock([SDLVideoStreamingCapability class]); + streamingLifecycleManager.videoStreamingCapabilityUpdated = videoStreamingCapabilityUpdated; + it(@"expect correct state", ^{ + expect(streamingLifecycleManager.videoStreamingCapabilityUpdated).notTo(beNil()); + expect(streamingLifecycleManager.videoStreamingCapabilityUpdated).to(equal(videoStreamingCapabilityUpdated)); + [streamingLifecycleManager didEnterStateVideoStreamStarting]; + expect(streamingLifecycleManager.videoStreamingCapabilityUpdated).to(beNil()); + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhileStarting).to(equal(videoStreamingCapabilityUpdated)); + }); + }); + }); + + context(@"init extended manager", ^{ + id<SDLConnectionManagerType> mockConnectionManager = OCMProtocolMock(@protocol(SDLConnectionManagerType)); + SDLConfiguration *configuration = [[SDLConfiguration alloc] init]; + SDLStreamingVideoLifecycleTestManager *streamingLifecycleManager = [[SDLStreamingVideoLifecycleTestManager alloc] initWithConnectionManager:mockConnectionManager configuration:configuration systemCapabilityManager:nil]; + + context(@"test didEnterStateVideoStreamReady", ^{ + it(@"expect displayLink update properly", ^{ + expect(streamingLifecycleManager.displayLink).to(beNil()); + [streamingLifecycleManager didEnterStateVideoStreamReady]; + expect([streamingLifecycleManager.displayLink isKindOfClass:[CADisplayLink class]]).toEventually(beTrue()); + }); + }); + + context(@"test didEnterStateVideoStreamSuspended", ^{ + SDLVideoStreamingCapability *videoStreamingCapabilityUpdated = OCMClassMock([SDLVideoStreamingCapability class]); + streamingLifecycleManager.videoStreamingCapabilityUpdated = videoStreamingCapabilityUpdated; + streamingLifecycleManager.shouldAutoResume = YES; + it(@"expect properties to update properly", ^{ + expect(streamingLifecycleManager.shouldAutoResume).to(equal(YES)); + expect(streamingLifecycleManager.videoStreamingCapabilityUpdated).notTo(beNil()); + expect(streamingLifecycleManager.videoStreamingCapabilityUpdated).to(equal(videoStreamingCapabilityUpdated)); + + [streamingLifecycleManager didEnterStateVideoStreamSuspended]; + + expect(streamingLifecycleManager.shouldAutoResume).to(equal(NO)); + expect(streamingLifecycleManager.videoStreamingCapability).toEventually(equal(videoStreamingCapabilityUpdated)); + expect(streamingLifecycleManager.shouldAutoResume).toEventually(equal(NO)); + + [streamingLifecycleManager.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStarting]; + SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]); + SDLProtocolMessage *startServiceNAK = OCMClassMock([SDLProtocolMessage class]); + SDLState *stateBefore = streamingLifecycleManager.videoStreamStateMachine.currentState; + [streamingLifecycleManager protocol:protocolMock didReceiveStartServiceNAK:startServiceNAK]; + SDLState *stateAfter = streamingLifecycleManager.videoStreamStateMachine.currentState; + + expect(stateBefore).to(equal(SDLVideoStreamManagerStateStarting)); + expect(stateAfter).to(equal(SDLVideoStreamManagerStateStarting)); + }); + }); + }); + + context(@"init extended manager", ^{ + id<SDLConnectionManagerType> mockConnectionManager = OCMProtocolMock(@protocol(SDLConnectionManagerType)); + SDLConfiguration *configuration = [[SDLConfiguration alloc] init]; + SDLStreamingVideoLifecycleTestManager *streamingLifecycleManager = [[SDLStreamingVideoLifecycleTestManager alloc] initWithConnectionManager:mockConnectionManager configuration:configuration systemCapabilityManager:nil]; + + context(@"test sdl_displayCapabilityDidUpdate", ^{ + streamingLifecycleManager.shouldAutoResume = YES; + SDLVideoStreamingCapability *videoStreamingCapabilityUpdated = OCMClassMock([SDLVideoStreamingCapability class]); + streamingLifecycleManager.videoStreamingCapabilityUpdated = videoStreamingCapabilityUpdated; + it(@"expect correct state", ^{ + SDLSystemCapability *systemCapability = nil; + [streamingLifecycleManager.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStarting]; + SDLState *stateBefore = streamingLifecycleManager.videoStreamStateMachine.currentState; + [streamingLifecycleManager sdl_displayCapabilityDidUpdate:systemCapability]; + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhileStarting).to(beNil()); + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhenStreaming).to(beNil()); + SDLState *stateAfter = streamingLifecycleManager.videoStreamStateMachine.currentState; + + expect(stateBefore).to(equal(SDLVideoStreamManagerStateStarting)); + expect(stateAfter).to(equal(SDLVideoStreamManagerStateStarting)); + + systemCapability = [[SDLSystemCapability alloc] init]; + systemCapability.videoStreamingCapability = OCMClassMock([SDLVideoStreamingCapability class]); + + stateBefore = streamingLifecycleManager.videoStreamStateMachine.currentState; + [streamingLifecycleManager sdl_displayCapabilityDidUpdate:systemCapability]; + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhileStarting).to(equal(systemCapability.videoStreamingCapability)); + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhenStreaming).to(beNil()); + stateAfter = streamingLifecycleManager.videoStreamStateMachine.currentState; + + expect(stateBefore).to(equal(SDLVideoStreamManagerStateStarting)); + expect(stateAfter).to(equal(SDLVideoStreamManagerStateStarting)); + + // state ready + streamingLifecycleManager.testVideoCapabilityUpdatedWhileStarting = nil; + streamingLifecycleManager.testVideoCapabilityUpdatedWhenStreaming = nil; + + [streamingLifecycleManager.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateReady]; + stateBefore = streamingLifecycleManager.videoStreamStateMachine.currentState; + [streamingLifecycleManager sdl_displayCapabilityDidUpdate:systemCapability]; + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhileStarting).to(beNil()); + expect(streamingLifecycleManager.testVideoCapabilityUpdatedWhenStreaming).to(equal(systemCapability.videoStreamingCapability)); + stateAfter = streamingLifecycleManager.videoStreamStateMachine.currentState; + + expect(stateBefore).to(equal(SDLVideoStreamManagerStateReady)); + expect(stateAfter).to(equal(SDLVideoStreamManagerStateReady)); + }); + }); + }); + +}); + describe(@"runtime tests", ^{ __block SDLStreamingVideoLifecycleManager *streamingLifecycleManager = nil; SDLStreamingMediaConfiguration *testConfiguration = [SDLStreamingMediaConfiguration insecureConfiguration]; @@ -226,6 +438,13 @@ describe(@"runtime tests", ^{ } }); + describe(@"QQQQQ", ^{ + context(@"", ^{ + ; + [streamingLifecycleManager suspendVideo]; + }); + }); + describe(@"when started", ^{ __block BOOL readyHandlerSuccess = NO; __block NSError *readyHandlerError = nil; diff --git a/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m index 483033569..d69f030f9 100644 --- a/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m +++ b/SmartDeviceLinkTests/ProtocolSpecs/MessageSpecs/SDLProtocolSpec.m @@ -35,9 +35,9 @@ NSDictionary* dictionaryV1 = @{SDLRPCParameterNameRequest: @{SDLRPCParameterNameCommandId:@55}}}; NSDictionary* dictionaryV2 = @{SDLRPCParameterNameCommandId:@55}; -describe(@"Send StartService Tests", ^ { +describe(@"Send StartService Tests", ^{ context(@"Insecure", ^{ - it(@"Should send the correct data", ^ { + it(@"Should send the correct data", ^{ // Reset max protocol version before test. (This test case expects V1 header. If other test ran // prior to this one, SDLGlobals would keep the max protocol version and this test case would fail.) [SDLGlobals sharedGlobals].maxHeadUnitProtocolVersion = [SDLVersion versionWithString:@"1.0.0"]; @@ -100,7 +100,7 @@ describe(@"Send StartService Tests", ^ { }); context(@"Secure", ^{ - it(@"Should send the correct data", ^ { + it(@"Should send the correct data", ^{ // TODO: How do we properly test the security? Assume a correct / fail? // TODO: The security methods need to be split out to their own class so they can be public. // Abstract Protocol needs to be combined into Protocol @@ -108,9 +108,9 @@ describe(@"Send StartService Tests", ^ { }); }); -describe(@"Send EndSession Tests", ^ { - context(@"During V1 session", ^ { - it(@"Should send the correct data", ^ { +describe(@"Send EndSession Tests", ^{ + context(@"During V1 session", ^{ + it(@"Should send the correct data", ^{ __block BOOL verified = NO; id transportMock = OCMProtocolMock(@protocol(SDLTransportType)); [[[transportMock stub] andDo:^(NSInvocation* invocation) { @@ -137,8 +137,8 @@ describe(@"Send EndSession Tests", ^ { }); }); - context(@"During V2 session", ^ { - it(@"Should send the correct data", ^ { + context(@"During V2 session", ^{ + it(@"Should send the correct data", ^{ __block BOOL verified = NO; id transportMock = OCMProtocolMock(@protocol(SDLTransportType)); [[[transportMock stub] andDo:^(NSInvocation* invocation) { @@ -166,8 +166,8 @@ describe(@"Send EndSession Tests", ^ { }); }); -describe(@"Send Register Secondary Transport Tests", ^ { - it(@"Should send the correct data", ^ { +describe(@"Send Register Secondary Transport Tests", ^{ + it(@"Should send the correct data", ^{ __block BOOL verified = NO; id transportMock = OCMProtocolMock(@protocol(SDLTransportType)); [[[transportMock stub] andDo:^(NSInvocation* invocation) { @@ -199,14 +199,14 @@ describe(@"Send Register Secondary Transport Tests", ^ { }); }); -describe(@"SendRPCRequest Tests", ^ { +describe(@"SendRPCRequest Tests", ^{ __block id mockRequest; - beforeEach(^ { + beforeEach(^{ mockRequest = OCMPartialMock([[SDLRPCRequest alloc] init]); }); - context(@"During V1 session", ^ { - it(@"Should send the correct data", ^ { + context(@"During V1 session", ^{ + it(@"Should send the correct data", ^{ [[[[mockRequest stub] andReturn:dictionaryV1] ignoringNonObjectArgs] serializeAsDictionary:1]; __block BOOL verified = NO; @@ -241,8 +241,8 @@ describe(@"SendRPCRequest Tests", ^ { }); }); - context(@"During V2 session", ^ { - it(@"Should send the correct data bulk data when bulk data is available", ^ { + context(@"During V2 session", ^{ + it(@"Should send the correct data bulk data when bulk data is available", ^{ [[[[mockRequest stub] andReturn:dictionaryV2] ignoringNonObjectArgs] serializeAsDictionary:2]; [[[mockRequest stub] andReturn:@0x98765] correlationID]; [[[mockRequest stub] andReturn:@"DeleteCommand"] name]; @@ -288,9 +288,9 @@ describe(@"SendRPCRequest Tests", ^ { }); }); -describe(@"HandleBytesFromTransport Tests", ^ { - context(@"During V1 session", ^ { -// it(@"Should parse the data correctly", ^ { +describe(@"HandleBytesFromTransport Tests", ^{ + context(@"During V1 session", ^{ +// it(@"Should parse the data correctly", ^{ // id routerMock = OCMClassMock(SDLProtocolReceivedMessageRouter.class); // // //Override initialization methods so that our protocol will use our object instead @@ -336,8 +336,8 @@ describe(@"HandleBytesFromTransport Tests", ^ { // }); }); - context(@"During V2 session", ^ { -// it(@"Should parse the data correctly", ^ { + context(@"During V2 session", ^{ +// it(@"Should parse the data correctly", ^{ // id routerMock = OCMClassMock(SDLProtocolReceivedMessageRouter.class); // // //Override initialization methods so that our protocol will use our object instead @@ -395,7 +395,7 @@ describe(@"HandleBytesFromTransport Tests", ^ { }); }); -describe(@"HandleProtocolSessionStarted tests", ^ { +describe(@"HandleProtocolSessionStarted tests", ^{ __block id transportMock = nil; __block SDLProtocol *testProtocol = nil; __block id delegateMock = nil; @@ -691,7 +691,7 @@ describe(@"HandleProtocolRegisterSecondaryTransport Tests", ^{ testProtocol = [[SDLProtocol alloc] initWithTransport:transportMock encryptionManager:nil]; }); - it(@"Should pass information along to delegate when ACKed", ^ { + it(@"Should pass information along to delegate when ACKed", ^{ id delegateMock = OCMProtocolMock(@protocol(SDLProtocolDelegate)); SDLV2ProtocolHeader* testHeader = [[SDLV2ProtocolHeader alloc] init]; @@ -711,7 +711,7 @@ describe(@"HandleProtocolRegisterSecondaryTransport Tests", ^{ OCMVerifyAllWithDelay(delegateMock, 0.1); }); - it(@"Should pass information along to delegate when NAKed", ^ { + it(@"Should pass information along to delegate when NAKed", ^{ id delegateMock = OCMProtocolMock(@protocol(SDLProtocolDelegate)); SDLV2ProtocolHeader* testHeader = [[SDLV2ProtocolHeader alloc] init]; @@ -750,12 +750,12 @@ describe(@"HandleHeartbeatForSession Tests", ^{ [testProtocol handleHeartbeatForSession:0x44]; }); - it(@"Should pass information along to delegate", ^ { + it(@"Should pass information along to delegate", ^{ OCMVerifyAllWithDelay(delegateMock, 0.1); }); }); -describe(@"OnProtocolMessageReceived Tests", ^ { +describe(@"OnProtocolMessageReceived Tests", ^{ __block id transportMock = nil; __block SDLProtocol *testProtocol = nil; __block id delegateMock = nil; @@ -776,12 +776,12 @@ describe(@"OnProtocolMessageReceived Tests", ^ { [testProtocol protocol:testProtocol didReceiveMessage:testMessage]; }); - it(@"Should pass information along to delegate", ^ { + it(@"Should pass information along to delegate", ^{ OCMVerifyAllWithDelay(delegateMock, 0.1); }); }); -describe(@"OnProtocolOpened Tests", ^ { +describe(@"OnProtocolOpened Tests", ^{ __block id transportMock = nil; __block SDLProtocol *testProtocol = nil; __block id delegateMock = nil; @@ -797,12 +797,12 @@ describe(@"OnProtocolOpened Tests", ^ { [testProtocol onTransportConnected]; }); - it(@"Should pass information along to delegate", ^ { + it(@"Should pass information along to delegate", ^{ OCMVerifyAllWithDelay(delegateMock, 0.1); }); }); -describe(@"OnProtocolClosed Tests", ^ { +describe(@"OnProtocolClosed Tests", ^{ __block id transportMock = nil; __block SDLProtocol *testProtocol = nil; __block id delegateMock = nil; @@ -818,9 +818,40 @@ describe(@"OnProtocolClosed Tests", ^ { [testProtocol onTransportDisconnected]; }); - it(@"Should pass information along to delegate", ^ { + it(@"Should pass information along to delegate", ^{ OCMVerifyAllWithDelay(delegateMock, 0.1); }); }); +describe(@"delegate table test", ^{ + id<SDLProtocolDelegate> mockDelegate = OCMProtocolMock(@protocol(SDLProtocolDelegate)); + id mockTransport = OCMProtocolMock(@protocol(SDLTransportType)); + __block SDLProtocol *testProtocol = nil; + + beforeEach(^{ + testProtocol = [[SDLProtocol alloc] initWithTransport:mockTransport encryptionManager:nil]; + // add the delegate twice though it must be added once only + [testProtocol addDelegate:mockDelegate]; + [testProtocol addDelegate:mockDelegate]; + }); + + context(@"test created protocol", ^{ + it(@"make sure object created", ^{ + expect(testProtocol).notTo(beNil()); + }); + + it(@"expect delegates table to contain one proper delegate alone", ^{ + expect(testProtocol.protocolDelegateTable.allObjects.count).to(equal(1)); + expect(testProtocol.protocolDelegateTable.allObjects.firstObject).to(equal(mockDelegate)); + }); + }); + + context(@"remove delegate", ^{ + it(@"expect delegates table to be empty", ^{ + [testProtocol removeDelegate:mockDelegate]; + expect(testProtocol.protocolDelegateTable.allObjects.count).to(equal(0)); + }); + }); +}); + QuickSpecEnd diff --git a/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnAppCapabilityUpdatedSpec.m b/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnAppCapabilityUpdatedSpec.m index e87a6ee6f..0c99cb4eb 100644 --- a/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnAppCapabilityUpdatedSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnAppCapabilityUpdatedSpec.m @@ -20,6 +20,9 @@ describe(@"getter/setter tests", ^{ context(@"init", ^{ SDLOnAppCapabilityUpdated *testStruct = [[SDLOnAppCapabilityUpdated alloc] init]; + it(@"expect object to be created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be nil", ^{ expect(testStruct.appCapability).to(beNil()); }); @@ -28,6 +31,9 @@ describe(@"getter/setter tests", ^{ context(@"init & assign", ^{ SDLOnAppCapabilityUpdated *testStruct = [[SDLOnAppCapabilityUpdated alloc] init]; testStruct.appCapability = appCapability; + it(@"expect object to be created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be set properly", ^{ expect(testStruct.appCapability).to(equal(appCapability)); }); @@ -35,6 +41,9 @@ describe(@"getter/setter tests", ^{ context(@"initWithVideoStreamingCapability:", ^{ SDLOnAppCapabilityUpdated *testStruct = [[SDLOnAppCapabilityUpdated alloc] initWithAppCapability:appCapability]; + it(@"expect object to be created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be set properly", ^{ expect(testStruct.appCapability).to(equal(appCapability)); }); @@ -50,6 +59,9 @@ describe(@"getter/setter tests", ^{ }; SDLOnAppCapabilityUpdated *testStruct = [[SDLOnAppCapabilityUpdated alloc] initWithDictionary:dict]; + it(@"expect object to be created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be set properly", ^{ expect(testStruct.appCapability).to(equal(appCapability)); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLAppCapabilitySpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLAppCapabilitySpec.m index 52ce00d68..6b3786027 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLAppCapabilitySpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLAppCapabilitySpec.m @@ -19,6 +19,9 @@ describe(@"getter/setter tests", ^{ context(@"init", ^{ SDLAppCapability *testStruct = [[SDLAppCapability alloc] init]; + it(@"make sure object created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be nil", ^{ expect(testStruct.appCapabilityType).to(beNil()); expect(testStruct.videoStreamingCapability).to(beNil()); @@ -29,6 +32,9 @@ describe(@"getter/setter tests", ^{ SDLAppCapability *testStruct = [[SDLAppCapability alloc] init]; testStruct.appCapabilityType = appCapabilityType; testStruct.videoStreamingCapability = videoStreamingCapability; + it(@"make sure object created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be set properly", ^{ expect(testStruct.appCapabilityType).to(equal(appCapabilityType)); expect(testStruct.videoStreamingCapability).to(equal(videoStreamingCapability)); @@ -37,6 +43,9 @@ describe(@"getter/setter tests", ^{ context(@"initWithVideoStreamingCapability:", ^{ SDLAppCapability *testStruct = [[SDLAppCapability alloc] initWithVideoStreamingCapability:videoStreamingCapability]; + it(@"make sure object created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be set properly", ^{ expect(testStruct.appCapabilityType).to(equal(appCapabilityType)); expect(testStruct.videoStreamingCapability).to(equal(videoStreamingCapability)); @@ -50,6 +59,9 @@ describe(@"getter/setter tests", ^{ }; SDLAppCapability *testStruct = [[SDLAppCapability alloc] initWithDictionary:dict]; + it(@"make sure object created", ^{ + expect(testStruct).notTo(beNil()); + }); it(@"expect all properties to be set properly", ^{ expect(testStruct.appCapabilityType).to(equal(appCapabilityType)); expect(testStruct.videoStreamingCapability).to(equal(videoStreamingCapability)); diff --git a/SmartDeviceLinkTests/TestStreamingMediaDelegate.h b/SmartDeviceLinkTests/TestStreamingMediaDelegate.h index d6153e096..bd4444faf 100644 --- a/SmartDeviceLinkTests/TestStreamingMediaDelegate.h +++ b/SmartDeviceLinkTests/TestStreamingMediaDelegate.h @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN @interface TestStreamingMediaDelegate : NSObject <SDLStreamingMediaDelegate> @property (nonatomic, readonly) NSArray *recordedSizes; +@property (nonatomic, assign) BOOL isStopped; - (void)reset; @end diff --git a/SmartDeviceLinkTests/TestStreamingMediaDelegate.m b/SmartDeviceLinkTests/TestStreamingMediaDelegate.m index a72bed029..bdbfd9b9a 100644 --- a/SmartDeviceLinkTests/TestStreamingMediaDelegate.m +++ b/SmartDeviceLinkTests/TestStreamingMediaDelegate.m @@ -39,6 +39,7 @@ - (void)videoManagerDidStop:(id)manager { SDLLogD(@"SDLStreamingMediaDelegate videoManagerDidStop"); + self.isStopped = YES; } @end |