summaryrefslogtreecommitdiff
path: root/SmartDeviceLinkTests
diff options
context:
space:
mode:
Diffstat (limited to 'SmartDeviceLinkTests')
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m23
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m42
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicUpdateOperationSpec.m114
-rw-r--r--SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLProtocolHeaderSpec.m38
-rw-r--r--SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV1ProtocolHeaderSpec.m17
-rw-r--r--SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV2ProtocolHeaderSpec.m17
-rw-r--r--SmartDeviceLinkTests/ProtocolSpecs/SDLProtocolReceivedMessageProcessorSpec.m769
-rw-r--r--SmartDeviceLinkTests/SDLPresentAlertOperationSpec.m39
-rw-r--r--SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m27
9 files changed, 1062 insertions, 24 deletions
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
index c663205e2..1ee9d5afd 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m
@@ -6,6 +6,7 @@
#import "SDLGlobals.h"
#import "SDLMenuManager.h"
+#import "SDLMenuShowOperation.h"
#import "SDLMenuReplaceOperation.h"
#import "TestConnectionManager.h"
@@ -17,6 +18,12 @@
@end
+@interface SDLMenuShowOperation()
+
+@property (strong, nonatomic, nullable) SDLMenuCell *submenuCell;
+
+@end
+
@interface SDLMenuManager()
@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
@@ -269,6 +276,22 @@ describe(@"menu manager", ^{
expect(canSendRPC).to(equal(YES));
});
+ // should queue an open menu operation for a copied submenu cell
+ it(@"should queue an open menu operation for a copied submenu cell and match the original cell id", ^ {
+ submenuCell.cellId = 1;
+ testManager.menuCells = @[submenuCell];
+
+ SDLMenuCell *copiedCell = [[SDLMenuCell alloc] initWithTitle:@"Test 3" secondaryText:nil tertiaryText:nil icon:nil secondaryArtwork:nil submenuLayout:nil subCells:@[textOnlyCell]];
+
+ BOOL canSendRPC = [testManager openMenu:copiedCell];
+ SDLMenuShowOperation *showOperation = (SDLMenuShowOperation *)testManager.transactionQueue.operations[1];
+
+ expect(showOperation.submenuCell.cellId).to(equal(submenuCell.cellId));
+ expect(showOperation.submenuCell.cellId).toNot(equal(copiedCell.cellId));
+ expect(testManager.transactionQueue.operationCount).to(equal(2));
+ expect(canSendRPC).to(equal(YES));
+ });
+
it(@"should cancel the first task if a second is queued", ^{
testManager.menuCells = @[submenuCell];
[testManager openMenu:nil];
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
index ea230248c..29e9a775f 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicManagerSpec.m
@@ -140,19 +140,23 @@ describe(@"text and graphic manager", ^{
});
});
- // when previous updates have bene cancelled
- context(@"when previous updates have bene cancelled", ^{
+ // without batching
+ context(@"without batching", ^{
beforeEach(^{
- testManager.textField1 = @"Hello";
-
- // This should cancel the first operation
- testManager.textField2 = @"Goodbye";
+ testManager.batchUpdates = NO;
+ testManager.textField1 = @"test1";
+ testManager.textField2 = @"test2";
+ testManager.textField3 = @"test3";
+ testManager.textField4 = @"test4";
});
- it(@"should properly queue the new update", ^{
+ it(@"should create individual operations and not be cancelled", ^{
expect(testManager.transactionQueue.isSuspended).to(beTrue());
- expect(testManager.transactionQueue.operationCount).to(equal(2));
- expect(testManager.transactionQueue.operations[0].cancelled).to(beTrue());
+ expect(testManager.transactionQueue.operationCount).to(equal(4));
+ expect(testManager.transactionQueue.operations[0].cancelled).to(beFalse());
+ expect(testManager.transactionQueue.operations[1].cancelled).to(beFalse());
+ expect(testManager.transactionQueue.operations[2].cancelled).to(beFalse());
+ expect(testManager.transactionQueue.operations[3].cancelled).to(beFalse());
});
});
@@ -450,6 +454,7 @@ describe(@"text and graphic manager", ^{
describe(@"when the operation updates the current screen data", ^{
__block SDLTextAndGraphicUpdateOperation *testOperation = nil;
__block SDLTextAndGraphicUpdateOperation *testOperation2 = nil;
+ __block SDLTextAndGraphicUpdateOperation *testOperation3 = nil;
beforeEach(^{
testManager.textField1 = @"test";
@@ -475,11 +480,26 @@ describe(@"text and graphic manager", ^{
beforeEach(^{
testManager.currentScreenData = [[SDLTextAndGraphicState alloc] init];
testManager.currentScreenData.textField1 = @"Test1";
- testOperation.currentDataUpdatedHandler(nil, [NSError errorWithDomain:@"any" code:1 userInfo:nil]);
+
+ // Create a "bad data" text field 1, then set it in the manager, which should create an operation (op 2)
+ SDLTextAndGraphicState *errorState = [[SDLTextAndGraphicState alloc] init];
+ errorState.textField1 = @"Bad Data";
+ testManager.textField1 = errorState.textField1;
+
+ // Create a "good data text field 4, which should create a second operation (op 3)
+ testManager.textField4 = @"Good Data";
+ testOperation3 = testManager.transactionQueue.operations[3];
+
+ // Simulate a failure of the first operation
+ NSDictionary *userInfo = @{
+ SDLTextAndGraphicFailedScreenStateErrorKey: errorState
+ };
+ testOperation.currentDataUpdatedHandler(nil, [NSError errorWithDomain:@"any" code:1 userInfo:userInfo]);
});
- it(@"should reset the manager's data", ^{
+ it(@"should reset the manager's data and update other operations updated state", ^{
expect(testManager.textField1).to(equal(testManager.currentScreenData.textField1));
+ expect(testOperation3.updatedState.textField1).to(equal(testManager.currentScreenData.textField1));
});
});
});
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicUpdateOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicUpdateOperationSpec.m
index b03252c25..a3f780ab0 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicUpdateOperationSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLTextAndGraphicUpdateOperationSpec.m
@@ -797,6 +797,116 @@ describe(@"the text and graphic operation", ^{
});
});
+ // updating with error state
+ describe(@"updating with error state", ^{
+ beforeEach(^{
+ updatedState = [[SDLTextAndGraphicState alloc] init];
+ updatedState.textField1 = field1String;
+ updatedState.textField2 = field2String;
+ updatedState.textField3 = field3String;
+ updatedState.textField4 = field4String;
+ updatedState.mediaTrackTextField = mediaTrackString;
+ updatedState.title = titleString;
+ updatedState.primaryGraphic = testArtwork;
+ updatedState.secondaryGraphic = testArtwork2;
+ updatedState.alignment = SDLTextAlignmentLeft;
+ updatedState.textField1Type = SDLMetadataTypeMediaTitle;
+ updatedState.textField2Type = SDLMetadataTypeMediaArtist;
+ updatedState.textField3Type = SDLMetadataTypeMediaAlbum;
+ updatedState.textField4Type = SDLMetadataTypeMediaYear;
+
+ emptyCurrentData = [[SDLTextAndGraphicState alloc] init];
+
+ testOp = [[SDLTextAndGraphicUpdateOperation alloc] initWithConnectionManager:testConnectionManager fileManager:mockFileManager currentCapabilities:windowCapability currentScreenData:emptyCurrentData newState:updatedState currentScreenDataUpdatedHandler:^(SDLTextAndGraphicState * _Nullable newScreenData, NSError * _Nullable error) {} updateCompletionHandler:nil];
+ [testOp start];
+ });
+
+ it(@"should reset to current screen data for equivalent properties in updated state and error state", ^{
+ // Create an error state that matches the updated state, which should reset the updated state
+ SDLTextAndGraphicState *errorState = [updatedState copy];
+ errorState.primaryGraphic = testArtwork;
+ errorState.secondaryGraphic = testArtwork2;
+
+ [testOp updateTargetStateWithErrorState:errorState];
+
+ expect(updatedState.textField1).to(beNil());
+ expect(updatedState.textField2).to(beNil());
+ expect(updatedState.textField3).to(beNil());
+ expect(updatedState.textField4).to(beNil());
+ expect(updatedState.mediaTrackTextField).to(beNil());
+ expect(updatedState.title).to(beNil());
+ expect(updatedState.primaryGraphic).to(beNil());
+ expect(updatedState.secondaryGraphic).to(beNil());
+ expect(updatedState.textField1Type).to(beNil());
+ expect(updatedState.textField2Type).to(beNil());
+ expect(updatedState.textField3Type).to(beNil());
+ expect(updatedState.textField4Type).to(beNil());
+ });
+
+ it(@"should not reset to current screen data for non equivalent properties in updated state and error state", ^{
+ // Save an original of the updatedState for confirming no changes later
+ SDLTextAndGraphicState *originalState = [updatedState copy];
+ originalState.primaryGraphic = testArtwork;
+ originalState.secondaryGraphic = testArtwork2;
+
+ // Create an error state that does not match the updated state, which should not reset the updated state
+ SDLTextAndGraphicState *errorState = [[SDLTextAndGraphicState alloc] init];
+ errorState.textField1 = @"Error Text";
+ errorState.textField2 = @"Error Text";
+ errorState.textField3 = @"Error Text";
+ errorState.textField4 = @"Error Text";
+ errorState.mediaTrackTextField = @"Error Text";
+ errorState.title = @"Error Text";
+ errorState.primaryGraphic = testArtwork2;
+ errorState.secondaryGraphic = testArtwork;
+ errorState.alignment = SDLTextAlignmentRight;
+ errorState.textField1Type = SDLMetadataTypeMediaYear;
+ errorState.textField2Type = SDLMetadataTypeMediaAlbum;
+ errorState.textField3Type = SDLMetadataTypeMediaArtist;
+ errorState.textField4Type = SDLMetadataTypeMediaTitle;
+
+ [testOp updateTargetStateWithErrorState:errorState];
+
+ expect(updatedState.textField1).to(equal(originalState.textField1));
+ expect(updatedState.textField2).to(equal(originalState.textField2));
+ expect(updatedState.textField3).to(equal(originalState.textField3));
+ expect(updatedState.textField4).to(equal(originalState.textField4));
+ expect(updatedState.mediaTrackTextField).to(equal(originalState.mediaTrackTextField));
+ expect(updatedState.title).to(equal(originalState.title));
+ expect(updatedState.primaryGraphic).to(equal(originalState.primaryGraphic));
+ expect(updatedState.secondaryGraphic).to(equal(originalState.secondaryGraphic));
+ expect(updatedState.textField1Type).to(equal(originalState.textField1Type));
+ expect(updatedState.textField2Type).to(equal(originalState.textField2Type));
+ expect(updatedState.textField3Type).to(equal(originalState.textField3Type));
+ expect(updatedState.textField4Type).to(equal(originalState.textField4Type));
+ });
+
+ it(@"should not reset to current screen data for nil error state", ^{
+ // Save an original of the updatedState for confirming no changes later
+ SDLTextAndGraphicState *originalState = [updatedState copy];
+ originalState.primaryGraphic = testArtwork;
+ originalState.secondaryGraphic = testArtwork2;
+
+ // Create an empty error state
+ SDLTextAndGraphicState *errorState = [[SDLTextAndGraphicState alloc] init];
+
+ [testOp updateTargetStateWithErrorState:errorState];
+
+ expect(updatedState.textField1).to(equal(originalState.textField1));
+ expect(updatedState.textField2).to(equal(originalState.textField2));
+ expect(updatedState.textField3).to(equal(originalState.textField3));
+ expect(updatedState.textField4).to(equal(originalState.textField4));
+ expect(updatedState.mediaTrackTextField).to(equal(originalState.mediaTrackTextField));
+ expect(updatedState.title).to(equal(originalState.title));
+ expect(updatedState.primaryGraphic).to(equal(originalState.primaryGraphic));
+ expect(updatedState.secondaryGraphic).to(equal(originalState.secondaryGraphic));
+ expect(updatedState.textField1Type).to(equal(originalState.textField1Type));
+ expect(updatedState.textField2Type).to(equal(originalState.textField2Type));
+ expect(updatedState.textField3Type).to(equal(originalState.textField3Type));
+ expect(updatedState.textField4Type).to(equal(originalState.textField4Type));
+ });
+ });
+
// updating image fields
describe(@"updating image fields", ^{
beforeEach(^{
@@ -933,6 +1043,8 @@ describe(@"the text and graphic operation", ^{
// Then it should return a failure and finish
expect(receivedState).to(beNil());
expect(receivedError).toNot(beNil());
+ expect(receivedError.userInfo[NSUnderlyingErrorKey]).toNot(beNil());
+ expect(receivedError.userInfo[SDLTextAndGraphicFailedScreenStateErrorKey]).to(equal(updatedState));
expect(completionError).toNot(beNil());
expect(testOp.isFinished).to(beTrue());
@@ -1295,6 +1407,8 @@ describe(@"the text and graphic operation", ^{
[testConnectionManager respondToLastRequestWithResponse:failShowResponse];
expect(receivedState).to(beNil());
expect(receivedError).toNot(beNil());
+ expect(receivedError.userInfo[NSUnderlyingErrorKey]).toNot(beNil());
+ expect(receivedError.userInfo[SDLTextAndGraphicFailedScreenStateErrorKey]).to(equal(updatedState));
expect(testOp.isFinished).to(beTrue());
});
diff --git a/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLProtocolHeaderSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLProtocolHeaderSpec.m
index a578ec561..9dac0203f 100644
--- a/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLProtocolHeaderSpec.m
+++ b/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLProtocolHeaderSpec.m
@@ -15,6 +15,18 @@
QuickSpecBegin(SDLProtocolHeaderSpec)
+__block SDLProtocolHeader *testHeader;
+
+beforeSuite(^ {
+ testHeader = [[SDLProtocolHeader alloc] init];
+ testHeader.encrypted = YES;
+ testHeader.frameType = SDLFrameTypeControl;
+ testHeader.serviceType = SDLServiceTypeRPC;
+ testHeader.frameData = SDLFrameInfoStartService;
+ testHeader.sessionID = 0x53;
+ testHeader.bytesInPayload = 0x1234;
+});
+
describe(@"HeaderForVersion Tests", ^ {
it(@"Should return the correct header", ^ {
expect([SDLProtocolHeader headerForVersion:1]).to(beAKindOf(SDLV1ProtocolHeader.class));
@@ -38,4 +50,30 @@ describe(@"DetermineVersion Tests", ^ {
});
});
+describe(@"hashing tests", ^ {
+ it(@"should return equivalent hash values", ^ {
+ SDLProtocolHeader *equalHeader = [[SDLProtocolHeader alloc] init];
+ equalHeader.encrypted = YES;
+ equalHeader.frameType = SDLFrameTypeControl;
+ equalHeader.serviceType = SDLServiceTypeRPC;
+ equalHeader.frameData = SDLFrameInfoStartService;
+ equalHeader.sessionID = 0x53;
+ equalHeader.bytesInPayload = 0x1234;
+
+ expect([testHeader hash]).to(equal([equalHeader hash]));
+ });
+
+ it(@"should return unequivalent hash values", ^ {
+ SDLProtocolHeader *unequalHeader = [[SDLProtocolHeader alloc] init];
+ unequalHeader.encrypted = NO;
+ unequalHeader.frameType = SDLFrameTypeFirst;
+ unequalHeader.serviceType = SDLServiceTypeVideo;
+ unequalHeader.frameData = SDLFrameInfoStartService;
+ unequalHeader.sessionID = 0x54;
+ unequalHeader.bytesInPayload = 0x1234;
+
+ expect([testHeader hash]).toNot(equal([unequalHeader hash]));
+ });
+});
+
QuickSpecEnd
diff --git a/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV1ProtocolHeaderSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV1ProtocolHeaderSpec.m
index a7c6c1660..f2218f7db 100644
--- a/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV1ProtocolHeaderSpec.m
+++ b/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV1ProtocolHeaderSpec.m
@@ -86,4 +86,21 @@ describe(@"RPCPayloadWithData Test", ^ {
});
});
+describe(@"equality tests", ^ {
+ it (@"should be equal to copy of header", ^ {
+ // Create exact copy of test header
+ SDLV1ProtocolHeader *equalHeader = [testHeader copy];
+
+ expect([testHeader isEqual:equalHeader]).to(beTrue());
+ });
+
+ it (@"should not be equal to a different header", ^ {
+ // create a slighty different version of test header
+ SDLV1ProtocolHeader *unequalHeader = [testHeader copy];
+ unequalHeader.encrypted = NO;
+
+ expect(([testHeader isEqual:unequalHeader])).to(beFalse());
+ });
+});
+
QuickSpecEnd
diff --git a/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV2ProtocolHeaderSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV2ProtocolHeaderSpec.m
index 1ade6e426..ec06d2b4d 100644
--- a/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV2ProtocolHeaderSpec.m
+++ b/SmartDeviceLinkTests/ProtocolSpecs/HeaderSpecs/SDLV2ProtocolHeaderSpec.m
@@ -90,4 +90,21 @@ describe(@"RPCPayloadWithData Test", ^ {
});
});
+describe(@"equality tests", ^ {
+ it (@"should be equal to copy of header", ^ {
+ // Create exact copy of test header
+ SDLV2ProtocolHeader *equalHeader = [testHeader copy];
+
+ expect([testHeader isEqual:equalHeader]).to(beTrue());
+ });
+
+ it (@"should not be equal to a different header", ^ {
+ // Create a slighty different version of test header
+ SDLV2ProtocolHeader *unequalHeader = [testHeader copy];
+ unequalHeader.messageID = 0x6DAB424E;
+
+ expect(([testHeader isEqual:unequalHeader])).to(beFalse());
+ });
+});
+
QuickSpecEnd
diff --git a/SmartDeviceLinkTests/ProtocolSpecs/SDLProtocolReceivedMessageProcessorSpec.m b/SmartDeviceLinkTests/ProtocolSpecs/SDLProtocolReceivedMessageProcessorSpec.m
new file mode 100644
index 000000000..7065e89a8
--- /dev/null
+++ b/SmartDeviceLinkTests/ProtocolSpecs/SDLProtocolReceivedMessageProcessorSpec.m
@@ -0,0 +1,769 @@
+//
+// SDLProtocolReceivedMessageProcessorSpec.m
+// SmartDeviceLinkTests
+//
+// Created by George Miller on 8/9/22.
+// Copyright © 2022 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLProtocol.h"
+#import "SDLProtocolReceivedMessageProcessor.h"
+#import "SDLV2ProtocolHeader.h"
+#import "SDLV2ProtocolMessage.h"
+
+typedef NS_ENUM(NSInteger, ProcessorState) {
+ START_STATE = 0x0,
+ SERVICE_TYPE_STATE = 0x01,
+ CONTROL_FRAME_INFO_STATE = 0x02,
+ SESSION_ID_STATE = 0x03,
+ DATA_SIZE_1_STATE = 0x04,
+ DATA_SIZE_2_STATE = 0x05,
+ DATA_SIZE_3_STATE = 0x06,
+ DATA_SIZE_4_STATE = 0x07,
+ MESSAGE_1_STATE = 0x08,
+ MESSAGE_2_STATE = 0x09,
+ MESSAGE_3_STATE = 0x0A,
+ MESSAGE_4_STATE = 0x0B,
+ DATA_PUMP_STATE = 0x0C,
+ ERROR_STATE = -1,
+};
+
+@interface SDLProtocolReceivedMessageProcessor ()
+// State management
+@property (assign, nonatomic) ProcessorState state;
+
+// Message assembly state
+@property (strong, nonatomic) SDLProtocolHeader *header;
+@property (strong, nonatomic) NSMutableData *headerBuffer;
+@property (strong, nonatomic) NSMutableData *payloadBuffer;
+
+@property (assign, nonatomic) UInt8 version;
+@property (assign, nonatomic) BOOL encrypted;
+@property (assign, nonatomic) SDLFrameType frameType;
+@property (assign, nonatomic) UInt32 dataLength;
+@property (assign, nonatomic) UInt32 dataBytesRemaining;
+@property (assign, nonatomic) SDLServiceType serviceType;
+@end
+
+QuickSpecBegin(SDLProtocolReceivedMessageProcessorSpec)
+
+describe(@"The received message processor", ^{
+ __block SDLProtocolReceivedMessageProcessor *testProcessor = nil;
+ __block NSMutableData *testBuffer;
+ __block NSMutableData *testHeaderBuffer;
+ __block SDLProtocolHeader *messageReadyHeader = nil;
+ __block SDLProtocolHeader *expectedMessageReadyHeader = nil;
+ __block NSData *messageReadyPayload = nil;
+ __block NSData *expectedPayloadBuffer = nil;
+
+ beforeEach(^{
+ testProcessor = [[SDLProtocolReceivedMessageProcessor alloc] init];
+ testBuffer = [NSMutableData data];
+ testHeaderBuffer = [NSMutableData data];
+ messageReadyHeader = nil;
+ expectedMessageReadyHeader = nil;
+ messageReadyPayload = nil;
+ });
+
+ it(@"test processor should be initialized correctly", ^{
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.version)).to(equal(0));
+ expect(@(testProcessor.encrypted)).to(equal(NO));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeControl));
+ expect(@(testProcessor.dataLength)).to(equal(0));
+ expect(@(testProcessor.dataBytesRemaining)).to(equal(0));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeControl));
+ });
+
+ describe(@"when in START_STATE", ^{
+ it(@"should transition to next state when receiving version 1", ^{
+ Byte testByte = 0x11;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(testProcessor.version).to(equal(1));
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ });
+
+ it(@"should transition to next state when receiving version 2", ^{
+ Byte testByte = 0x21;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(testProcessor.version).to(equal(2));
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ });
+
+ it(@"should transition to next state when receiving version 3", ^{
+ Byte testByte = 0x31;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(testProcessor.version).to(equal(3));
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ });
+
+ it(@"should transition to next state when receiving version 4", ^{
+ Byte testByte = 0x41;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(testProcessor.version).to(equal(4));
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ });
+
+ it(@"should transition to next state when receiving version 5", ^{
+ Byte testByte = 0x51;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(testProcessor.version).to(equal(5));
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ });
+
+ it(@"should transition to next state when receiving a byte with a frameType of SDLFrameTypeControl", ^{
+ Byte testByte = 0x10;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ });
+
+ it(@"should transition to next state when receiving a byte with a frameType of SDLFrameTypeSingle", ^{
+ Byte testByte = 0x11;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeSingle));
+ });
+
+ it(@"should transition to next state when receiving a byte with a frameType of SDLFrameTypeFirst", ^{
+ Byte testByte = 0x12;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeFirst));
+ });
+
+ it(@"should transition to next state when receiving a byte with a frameType of SDLFrameTypeConsecutive", ^{
+ Byte testByte = 0x13;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(SERVICE_TYPE_STATE));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeConsecutive));
+ });
+
+ it(@"should reset state when receiving a byte with a bad version 0", ^{
+ Byte testByte = 0x01;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(testProcessor.version).to(equal(0));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ });
+
+ it(@"should reset state when receiving a byte with a bad version 6", ^{
+ Byte testByte = 0x61;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(testProcessor.version).to(equal(0));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ });
+
+ it(@"should reset state when receiving a byte with an invalid frameType of 6", ^{
+ Byte testByte = 0x46; //0100 0 110
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.frameType)).to(equal(0));
+ expect(testProcessor.version).to(equal(0));
+ });
+ });
+
+ // transitions to CONTROL_FRAME_INFO_STATE when in SERVICE_TYPE_STATE
+ describe(@"when in SERVICE_TYPE_STATE", ^{
+
+ beforeEach(^{
+ testProcessor.state = SERVICE_TYPE_STATE;
+ });
+
+ it(@"should transition to next state when receiving a SDLServiceTypeControl byte", ^{
+ Byte testByte = SDLServiceTypeControl;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(CONTROL_FRAME_INFO_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeControl));
+ });
+
+ it(@"should transition to next state when receiving a SDLServiceTypeRPC byte", ^{
+ Byte testByte = SDLServiceTypeRPC;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(CONTROL_FRAME_INFO_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeRPC));
+ });
+
+ it(@"should transition to next state when receiving a SDLServiceTypeAudio byte", ^{
+ Byte testByte = SDLServiceTypeAudio;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(CONTROL_FRAME_INFO_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeAudio));
+ });
+
+ it(@"should transition to next state when receiving a SDLServiceTypeVideo byte", ^{
+ Byte testByte = SDLServiceTypeVideo;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(CONTROL_FRAME_INFO_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeVideo));
+ });
+
+ it(@"should transition to next state when receiving a SDLServiceTypeBulkData byte", ^{
+ Byte testByte = SDLServiceTypeBulkData;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(CONTROL_FRAME_INFO_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeBulkData));
+ });
+
+ it(@"should reset state when receiving an invalid byte", ^{
+ Byte testByte = 0xFF;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(SDLServiceTypeControl));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ });
+ });
+
+ describe(@"when in CONTROL_FRAME_INFO_STATE", ^{
+
+ beforeEach(^{
+ testProcessor.state = CONTROL_FRAME_INFO_STATE;
+ });
+
+ it(@"should transition to next state when receiving a valid byte", ^{
+ Byte testByte = 0x00;
+ testProcessor.frameType = SDLFrameTypeFirst;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(SESSION_ID_STATE));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeFirst));
+ });
+
+ it(@"should reset state when receiving a byte where controlFrameInfo is not 0 and frameType is SDLFrameTypeFirst", ^{
+ Byte testByte = 0x01;
+ testProcessor.frameType = SDLFrameTypeFirst;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeControl));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ });
+
+ it(@"should resets state when receiving a byte where controlFrameInfo is not 0 and frameType is SDLFrameTypeSingle", ^{
+ Byte testByte = 0x01;
+ testProcessor.frameType = SDLFrameTypeSingle;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.frameType)).to(equal(SDLFrameTypeControl));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ });
+ });
+
+ it(@"should transition to DATA_SIZE_1_STATE when in SESSION_ID_STATE and receiving a byte", ^{
+ testProcessor.state = SESSION_ID_STATE;
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_SIZE_1_STATE));
+ expect(@(testProcessor.dataLength)).to(equal(0));
+ });
+
+ it(@"should transition to DATA_SIZE_2_STATE when in DATA_SIZE_1_STATE and receiving a byte", ^{
+ testProcessor.state = DATA_SIZE_1_STATE;
+ Byte testByte = 0x02;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_SIZE_2_STATE));
+ expect(@(testProcessor.dataLength)).to(equal((UInt32)(testByte & 0xFF) << 24));
+ });
+
+ it(@"should transitions to DATA_SIZE_3_STATE when in DATA_SIZE_2_STATE and receiving a byte", ^{
+ testProcessor.state = DATA_SIZE_2_STATE;
+ Byte testByte = 0x02;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_SIZE_3_STATE));
+ expect(@(testProcessor.dataLength)).to(equal((UInt32)(testByte & 0xFF) << 16));
+ });
+
+ it(@"should transition to DATA_SIZE_4_STATE when in DATA_SIZE_3_STATE and receiving a byte", ^{
+ testProcessor.state = DATA_SIZE_3_STATE;
+ Byte testByte = 0x02;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_SIZE_4_STATE));
+ expect(@(testProcessor.dataLength)).to(equal((UInt32)(testByte & 0xFF) << 8));
+ });
+
+ describe(@"when in DATA_SIZE_4_STATE and the version is 1", ^{
+ beforeEach(^{
+ testProcessor.state = DATA_SIZE_4_STATE;
+ testProcessor.version = 1;
+
+ messageReadyHeader = nil;
+ messageReadyPayload = nil;
+
+ //need a valid headerbuffer.
+ Byte firstByte = ((testProcessor.version & 0x0f) << 4) + (0 << 3) + (1 & 0x07); //version 2 with no encryption, frametype 1
+ UInt32 dataLength = 3;
+ const Byte testBytes[8] = {firstByte, 0x00, 0x00, 0x00, (dataLength >> 24) & 0xff, (dataLength >> 16) & 0xff, (dataLength >> 8) & 0xff, (dataLength) & 0xff };
+ [testHeaderBuffer appendBytes:&testBytes length:8];
+ UInt32 messageID = 0;
+ Byte messageIDBytes[4] = {(messageID >> 24) & 0xff, (messageID >> 16) & 0xff, (messageID >> 8) & 0xff, (messageID) & 0xff};
+ [testHeaderBuffer appendBytes:&messageIDBytes length:4];
+
+ testProcessor.headerBuffer = testHeaderBuffer;
+ expectedMessageReadyHeader= [SDLProtocolHeader headerForVersion:testProcessor.version];
+ [expectedMessageReadyHeader parse:testHeaderBuffer];
+
+ expectedPayloadBuffer = [NSData data];
+ });
+
+ it(@"should reset state when receiving a byte and determines the data length is 0", ^{
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+ messageReadyHeader = [SDLProtocolHeader headerForVersion:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(equal(expectedMessageReadyHeader));
+ expect(messageReadyPayload).to(equal(expectedPayloadBuffer));
+ }];
+ expect(@(testProcessor.dataLength)).to(equal(0));
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.version)).to(equal(0));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ });
+
+ it(@"should transition to DATA_PUMP_STATE when receiving a byte and determines the data length is greater than 0", ^{
+ Byte testByte = 0x01;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_PUMP_STATE));
+ expect(@(testProcessor.dataLength)).to(equal(1));
+ expect(@(testProcessor.version)).to(equal(1));
+ });
+
+ it(@"should transition to START_STATE when receiving a byte and determines the data length is greater than maxMtuSize", ^{
+ testProcessor.serviceType = SDLServiceTypeControl;
+ testProcessor.dataLength = 200000;
+
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(@(testProcessor.serviceType)).to(equal(0));
+ expect(@(testProcessor.dataLength)).to(equal(0));
+ expect(@(testProcessor.version)).to(equal(0));
+ });
+ });
+
+ describe(@"when in DATA_SIZE_4_STATE and the version is greater than 1", ^{
+ beforeEach(^{
+ testProcessor.state = DATA_SIZE_4_STATE;
+ messageReadyHeader = nil;
+ messageReadyPayload = nil;
+
+ testProcessor.version = 1;
+ //need a valid headerbuffer.
+ Byte firstByte = ((testProcessor.version & 0x0f) << 4) + (0 << 3) + (1 & 0x07); //version 2 with no encryption, frametype 1
+ UInt32 dataLength = 3;
+ const Byte testBytes[8] = {firstByte, 0x00, 0x00, 0x00, (dataLength >> 24) & 0xff, (dataLength >> 16) & 0xff, (dataLength >> 8) & 0xff, (dataLength) & 0xff };
+ [testHeaderBuffer appendBytes:&testBytes length:8];
+ UInt32 messageID = 0;
+ Byte messageIDBytes[4] = {(messageID >> 24) & 0xff, (messageID >> 16) & 0xff, (messageID >> 8) & 0xff, (messageID) & 0xff};
+ [testHeaderBuffer appendBytes:&messageIDBytes length:4];
+
+ testProcessor.headerBuffer = testHeaderBuffer;
+ expectedMessageReadyHeader= [SDLProtocolHeader headerForVersion:testProcessor.version];
+ [expectedMessageReadyHeader parse:testHeaderBuffer];
+
+ expectedPayloadBuffer = [NSData data];
+ });
+
+ it(@"should transition to MESSAGE_1_STATE when it receives a byte", ^{
+ testProcessor.version = 2;
+ testProcessor.dataLength = 0;
+
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(MESSAGE_1_STATE));
+ expect(testProcessor.version).to(equal(2));
+ });
+ });
+
+ it(@"should transition to MESSAGE_2_STATE when in MESSAGE_1_STATE, it receives a byte", ^{
+ testProcessor.state = MESSAGE_1_STATE;
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(MESSAGE_2_STATE));
+ });
+
+ it(@"should transition to MESSAGE_3_STATE when in MESSAGE_2_STATE and it receives a byte", ^{
+ testProcessor.state = MESSAGE_2_STATE;
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(MESSAGE_3_STATE));
+ });
+
+ it(@"should transition to MESSAGE_4_STATE when in MESSAGE_3_STATE and it receives a byte", ^{
+ testProcessor.state = MESSAGE_3_STATE;
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(MESSAGE_4_STATE));
+ });
+
+ describe(@"when in MESSAGE_4_STATE and version is greater than 1", ^{
+ beforeEach(^{
+ testProcessor.state = MESSAGE_4_STATE;
+ testProcessor.version = 2;
+ //need a valid headerbuffer.
+ Byte firstByte = ((testProcessor.version & 0x0f) << 4) + (0 << 3) + (1 & 0x07); //version 2 with no encryption, frametype 1
+ UInt32 dataLength = 3;
+ const Byte testBytes[8] = {firstByte, 0x00, 0x00, 0x00, (dataLength >> 24) & 0xff, (dataLength >> 16) & 0xff, (dataLength >> 8) & 0xff, (dataLength) & 0xff };
+ [testHeaderBuffer appendBytes:&testBytes length:8];
+ UInt32 messageID = 0;
+ Byte messageIDBytes[4] = {(messageID >> 24) & 0xff, (messageID >> 16) & 0xff, (messageID >> 8) & 0xff, (messageID) & 0xff};
+ [testHeaderBuffer appendBytes:&messageIDBytes length:4];
+
+ testProcessor.headerBuffer = testHeaderBuffer;
+ expectedMessageReadyHeader= [SDLProtocolHeader headerForVersion:testProcessor.version];
+ [expectedMessageReadyHeader parse:testHeaderBuffer];
+
+ expectedPayloadBuffer = [NSData data];
+
+ messageReadyHeader = nil;
+ messageReadyPayload = nil;
+
+ Byte testByte = 0x00;
+ [testBuffer appendBytes:&testByte length:1];
+ });
+
+ it(@"should reset state when data length is 0 and receiving a byte", ^{
+ testProcessor.dataLength = 0;
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(equal(expectedMessageReadyHeader));
+ expect(messageReadyPayload).to(equal(expectedPayloadBuffer));
+ }];
+ expect(testProcessor.version).to(equal(0));
+ expect(testProcessor.headerBuffer).to(equal([NSMutableData data]));
+ expect(testProcessor.payloadBuffer).to(equal([NSMutableData data]));
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ });
+
+ it(@"should transition to DATA_PUMP_STATE when datalength is greater than 0 and receiving a byte", ^{
+ testProcessor.dataLength = 1;
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_PUMP_STATE));
+ expect(testProcessor.version).to(equal(2));
+ });
+ });
+
+ describe(@"in DATA_PUMP_STATE", ^{
+ beforeEach(^{
+ testProcessor.state = DATA_PUMP_STATE;
+ testProcessor.version = 3;
+ //need a valid header buffer.
+ Byte firstByte = ((testProcessor.version & 0x0f) << 4) + (0 << 3) + (1 & 0x07); //version 2 with no encryption, frametype 1
+ UInt32 dataLength = 3;
+ const Byte testBytes[8] = {firstByte, 0x00, 0x00, 0x00, (dataLength >> 24) & 0xff, (dataLength >> 16) & 0xff, (dataLength >> 8) & 0xff, (dataLength) & 0xff };
+ [testHeaderBuffer appendBytes:&testBytes length:8];
+ UInt32 messageID = 0;
+ Byte messageIDBytes[4] = {(messageID >> 24) & 0xff, (messageID >> 16) & 0xff, (messageID >> 8) & 0xff, (messageID) & 0xff};
+ [testHeaderBuffer appendBytes:&messageIDBytes length:4];
+
+ testProcessor.headerBuffer = testHeaderBuffer;
+ expectedMessageReadyHeader= [SDLProtocolHeader headerForVersion:testProcessor.version];
+ [expectedMessageReadyHeader parse:testHeaderBuffer];
+
+ Byte testByte = 0xBA;
+ [testBuffer appendBytes:&testByte length:1];
+ });
+
+ it(@"should stay in current state when dataBytesRemaining is greater than 1 and receiving a byte", ^{
+ testProcessor.dataBytesRemaining = 2;
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(beNil());
+ expect(messageReadyPayload).to(beNil());
+ }];
+ expect(@(testProcessor.state)).to(equal(DATA_PUMP_STATE));
+ expect(testProcessor.dataBytesRemaining).to(equal(1));
+ expect(testProcessor.version).to(equal(3));
+ });
+
+ it(@"should transition to START_STATE when dataBytesRemaining is 1 and receiving a byte", ^{
+ testProcessor.dataBytesRemaining = 1;
+
+ [testProcessor processReceiveBuffer:testBuffer withMessageReadyBlock:^(SDLProtocolHeader *header, NSData *payload) {
+ messageReadyHeader = header;
+ messageReadyPayload = payload;
+
+ expect(messageReadyHeader).to(equal(expectedMessageReadyHeader));
+ expect(messageReadyPayload).to(equal(testBuffer));
+ }];
+ expect(testProcessor.dataBytesRemaining).to(equal(0));
+ expect(@(testProcessor.state)).to(equal(START_STATE));
+ expect(testProcessor.version).to(equal(0));
+ });
+ });
+});
+
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/SDLPresentAlertOperationSpec.m b/SmartDeviceLinkTests/SDLPresentAlertOperationSpec.m
index 78dda1e82..4173b923d 100644
--- a/SmartDeviceLinkTests/SDLPresentAlertOperationSpec.m
+++ b/SmartDeviceLinkTests/SDLPresentAlertOperationSpec.m
@@ -42,6 +42,7 @@
@property (strong, nonatomic, readwrite) SDLAlertView *alertView;
@property (assign, nonatomic) UInt16 cancelId;
@property (copy, nonatomic, nullable) NSError *internalError;
+@property (assign, nonatomic) BOOL alertIconUploaded;
- (nullable NSError *)sdl_isValidAlertViewData:(SDLAlertView *)alertView;
- (SDLAlert *)alertRPC;
@@ -365,16 +366,16 @@ describe(@"SDLPresentAlertOperation", ^{
testPresentAlertOperation = [[SDLPresentAlertOperation alloc] initWithConnectionManager:mockConnectionManager fileManager:mockFileManager systemCapabilityManager:mockSystemCapabilityManager currentWindowCapability:mockCurrentWindowCapability alertView:testAlertView cancelID:testCancelID];
});
- it(@"should set the image if icons are supported on the module", ^{
- OCMStub([mockCurrentWindowCapability hasImageFieldOfName:SDLImageFieldNameAlertIcon]).andReturn(YES);
+ it(@"should not set the image if it fails to upload to the module", ^{
SDLAlert *testAlert = testPresentAlertOperation.alertRPC;
- expect(testAlert.alertIcon.value).to(equal(testAlertView.icon.name));
+ expect(testAlert.alertIcon.value).to(beNil());
});
- it(@"should not set the image if icons are not supported on the module", ^{
- OCMStub([mockCurrentWindowCapability hasImageFieldOfName:SDLImageFieldNameAlertIcon]).andReturn(NO);
+ it(@"should set the image if it is uploaded to the module", ^{
+ testPresentAlertOperation.alertIconUploaded = YES;
+
SDLAlert *testAlert = testPresentAlertOperation.alertRPC;
- expect(testAlert.alertIcon).to(beNil());
+ expect(testAlert.alertIcon.value).to(equal(testAlertView.icon.name));
});
});
});
@@ -635,6 +636,25 @@ describe(@"SDLPresentAlertOperation", ^{
OCMVerifyAll(strictMockSystemCapabilityManager);
OCMVerifyAll(strictMockCurrentWindowCapability);
});
+
+ it(@"should not upload the image if the alert icon is a static icon", ^{
+ SDLAlertView *alertView = [[SDLAlertView alloc] initWithText:@"Test" secondaryText:nil tertiaryText:nil timeout:nil showWaitIndicator:nil audioIndication:nil buttons:nil icon:[SDLArtwork artworkWithStaticIcon:SDLStaticIconNameKey]];
+ testPresentAlertOperation = [[SDLPresentAlertOperation alloc] initWithConnectionManager:mockConnectionManager fileManager:strictMockFileManager systemCapabilityManager:strictMockSystemCapabilityManager currentWindowCapability:strictMockCurrentWindowCapability alertView:alertView cancelID:testCancelID];
+
+ OCMStub([strictMockCurrentWindowCapability hasImageFieldOfName:SDLImageFieldNameAlertIcon]).andReturn(YES);
+ OCMStub([strictMockFileManager hasUploadedFile:[OCMArg any]]).andReturn(NO);
+ OCMStub([strictMockFileManager fileNeedsUpload:[OCMArg any]]).andReturn(NO);
+
+ OCMReject([strictMockFileManager uploadArtworks:[OCMArg any] progressHandler:[OCMArg any] completionHandler:[OCMArg any]]);
+
+ [testPresentAlertOperation start];
+
+ OCMVerifyAll(strictMockFileManager);
+ OCMVerifyAll(strictMockSystemCapabilityManager);
+ OCMVerifyAll(strictMockCurrentWindowCapability);
+ expect(testPresentAlertOperation.alertIconUploaded).to(beTrue());
+ expect(testPresentAlertOperation.alertRPC.alertIcon).toNot(beNil());
+ });
});
});
@@ -781,6 +801,7 @@ describe(@"SDLPresentAlertOperation", ^{
testAlertViewWithExtraSoftButtons = [[SDLAlertView alloc] initWithText:@"text" secondaryText:@"secondaryText" tertiaryText:@"tertiaryText" timeout:@(4) showWaitIndicator:@(YES) audioIndication:testAlertAudioData buttons:@[testAlertSoftButton1, testAlertSoftButton2, testAlertSoftButton3, testAlertSoftButton4, testAlertSoftButton5, testAlertSoftButton6] icon:testAlertIcon];
testPresentAlertOperation = [[SDLPresentAlertOperation alloc] initWithConnectionManager:mockConnectionManager fileManager:mockFileManager systemCapabilityManager:mockSystemCapabilityManager currentWindowCapability:mockCurrentWindowCapability alertView:testAlertViewWithExtraSoftButtons cancelID:testCancelID];
+ testPresentAlertOperation.alertIconUploaded = YES;
testPresentAlertOperation.completionBlock = ^{
hasCalledOperationCompletionHandler = YES;
@@ -829,7 +850,7 @@ describe(@"SDLPresentAlertOperation", ^{
testSoftButtonCapabilities.imageSupported = @YES;
OCMStub([mockCurrentWindowCapability softButtonCapabilities]).andReturn(@[testSoftButtonCapabilities]);
OCMStub([mockFileManager fileNeedsUpload:[OCMArg any]]).andReturn(YES);
- OCMStub([mockFileManager uploadArtworks:[OCMArg any] progressHandler:[OCMArg invokeBlock] completionHandler:([OCMArg invokeBlockWithArgs: @[testAlertView.icon.name], [NSNull null], nil])]);
+ OCMStub([mockFileManager uploadArtworks:[OCMArg any] progressHandler:[OCMArg invokeBlock] completionHandler:([OCMArg invokeBlockWithArgs: @[], [NSNull null], nil])]);
OCMStub([mockFileManager uploadFiles:[OCMArg any] progressHandler:[OCMArg invokeBlock] completionHandler:[OCMArg invokeBlock]]);
SDLVersion *supportedVersion = [SDLVersion versionWithMajor:6 minor:3 patch:0];
@@ -883,8 +904,8 @@ describe(@"SDLPresentAlertOperation", ^{
SDLSoftButtonCapabilities *testSoftButtonCapabilities = [[SDLSoftButtonCapabilities alloc] init];
testSoftButtonCapabilities.imageSupported = @YES;
OCMStub([mockCurrentWindowCapability softButtonCapabilities]).andReturn(@[testSoftButtonCapabilities]);
- OCMStub([mockFileManager fileNeedsUpload:[OCMArg any]]).andReturn(NO);
- OCMStub([mockFileManager uploadArtworks:[OCMArg any] progressHandler:[OCMArg invokeBlock] completionHandler:[OCMArg invokeBlock]]);
+ OCMStub([mockFileManager fileNeedsUpload:[OCMArg any]]).andReturn(YES);
+ OCMStub([mockFileManager uploadArtworks:[OCMArg any] progressHandler:[OCMArg invokeBlock] completionHandler:([OCMArg invokeBlockWithArgs: @[testAlertView.icon.name], [NSNull null], nil])]);
OCMStub([mockFileManager uploadFiles:[OCMArg any] progressHandler:[OCMArg invokeBlock] completionHandler:[OCMArg invokeBlock]]);
SDLVersion *supportedVersion = [SDLVersion versionWithMajor:6 minor:3 patch:0];
diff --git a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
index 613030611..5343c4397 100644
--- a/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLSystemCapabilityManagerSpec.m
@@ -95,9 +95,16 @@ describe(@"a system capability manager", ^{
imageField.imageTypeSupported = @[SDLFileTypePNG];
imageField.imageResolution = [[SDLImageResolution alloc] initWithWidth:42 height:4711];
testDisplayCapabilities.imageFields = @[imageField];
- testDisplayCapabilities.mediaClockFormats = @[];
+ testDisplayCapabilities.mediaClockFormats = @[SDLMediaClockFormatClock1, SDLMediaClockFormatClock2];
testDisplayCapabilities.templatesAvailable = @[@"DEFAULT", @"MEDIA"];
testDisplayCapabilities.numCustomPresetsAvailable = @(8);
+ SDLScreenParams *screenParams = [[SDLScreenParams alloc] init];
+ [screenParams setResolution:[[SDLImageResolution alloc] initWithWidth:675 height:960]];
+ [screenParams setTouchEventAvailable:[[SDLTouchEventCapabilities alloc] init]];
+ [screenParams.touchEventAvailable setPressAvailable:@YES];
+ [screenParams.touchEventAvailable setMultiTouchAvailable:@YES];
+ [screenParams.touchEventAvailable setDoublePressAvailable:@YES];
+ testDisplayCapabilities.screenParams = screenParams;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -702,18 +709,28 @@ describe(@"a system capability manager", ^{
expect(testSystemCapabilityManager.defaultMainWindowCapability.textFields).to(haveCount(38));
expect(testSystemCapabilityManager.defaultMainWindowCapability.imageFields).to(haveCount(18));
});
+
+ it(@"should set the default window id if window id is missing", ^{
+ // Set window id to nil. windowID can be potentially nil in real applications
+ testSystemCapabilityManager.displays[0].windowCapabilities[0].windowID = nil;
+
+ expect(testSystemCapabilityManager.defaultMainWindowCapability.windowID).to(equal(SDLPredefinedWindowsDefaultWindow));
+ expect([testSystemCapabilityManager windowCapabilityWithWindowID:0].windowID).to(equal(SDLPredefinedWindowsDefaultWindow));
+ });
});
});
// when updating display capabilities with OnSystemCapabilityUpdated
describe(@"when updating display capabilities with OnSystemCapabilityUpdated", ^{
it(@"should properly update display capability including conversion two times", ^{
+ // Set to display capabilities that have screenParams and mediaClockFormats set
+ testSystemCapabilityManager.displayCapabilities = testDisplayCapabilities;
// two times because capabilities are just saved in first run but merged/updated in subsequent runs
for (int i = 0; i < 2; i++) {
testDisplayCapabilities.displayName = [NSString stringWithFormat:@"Display %i", i];
testDisplayCapabilities.graphicSupported = i == 0 ? @(NO) : @(YES);
testDisplayCapabilities.templatesAvailable = @[[NSString stringWithFormat:@"Template %i", i]];
-
+
SDLWindowTypeCapabilities *windowTypeCapabilities = [[SDLWindowTypeCapabilities alloc] initWithType:SDLWindowTypeMain maximumNumberOfWindows:1];
SDLDisplayCapability *displayCapability = [[SDLDisplayCapability alloc] initWithDisplayName:testDisplayCapabilities.displayName];
displayCapability.windowTypeSupported = @[windowTypeCapabilities];
@@ -728,16 +745,18 @@ describe(@"a system capability manager", ^{
defaultWindowCapability.imageTypeSupported = testDisplayCapabilities.graphicSupported.boolValue ? @[SDLImageTypeStatic, SDLImageTypeDynamic] : @[SDLImageTypeStatic];
displayCapability.windowCapabilities = @[defaultWindowCapability];
NSArray<SDLDisplayCapability *> *newDisplayCapabilityList = testDisplayCapabilityList = @[displayCapability];
-
+
SDLSystemCapability *newCapability = [[SDLSystemCapability alloc] initWithDisplayCapabilities:newDisplayCapabilityList];
SDLOnSystemCapabilityUpdated *testUpdateNotification = [[SDLOnSystemCapabilityUpdated alloc] initWithSystemCapability:newCapability];
SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveSystemCapabilityUpdatedNotification object:nil rpcNotification:testUpdateNotification];
[[NSNotificationCenter defaultCenter] postNotification:notification];
-
+
expect(testSystemCapabilityManager.displays).to(equal(testDisplayCapabilityList));
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
expect(testSystemCapabilityManager.displayCapabilities).to(equal(testDisplayCapabilities));
+ expect(testSystemCapabilityManager.displayCapabilities.screenParams).to(equal(testDisplayCapabilities.screenParams));
+ expect(testSystemCapabilityManager.displayCapabilities.mediaClockFormats).to(equal(testDisplayCapabilities.mediaClockFormats));
expect(testSystemCapabilityManager.buttonCapabilities).to(equal(testButtonCapabilities));
expect(testSystemCapabilityManager.softButtonCapabilities).to(equal(testSoftButtonCapabilities));
expect(testSystemCapabilityManager.presetBankCapabilities).to(beNil());