Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSL1g4 #362

Merged
merged 7 commits into from
Apr 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Source/ARTRestChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,22 @@ - (void)internalPostMessages:(id)data callback:(void (^)(ARTErrorInfo *__art_nul

if ([data isKindOfClass:[ARTMessage class]]) {
ARTMessage *message = (ARTMessage *)data;
message.clientId = self.rest.auth.clientId;
if (message.clientId && self.rest.auth.clientId && ![message.clientId isEqualToString:self.rest.auth.clientId]) {
callback([ARTErrorInfo createWithCode:ARTStateMismatchedClientId message:@"attempted to publish message with an invalid clientId"]);
return;
}
else {
message.clientId = self.rest.auth.clientId;
}
encodedMessage = [self.rest.defaultEncoder encodeMessage:message];
} else if ([data isKindOfClass:[NSArray class]]) {
__GENERIC(NSArray, ARTMessage *) *messages = (NSArray *)data;
for (ARTMessage *message in messages) {
if (message.clientId && self.rest.auth.clientId && ![message.clientId isEqualToString:self.rest.auth.clientId]) {
callback([ARTErrorInfo createWithCode:ARTStateMismatchedClientId message:@"attempted to publish message with an invalid clientId"]);
return;
}
}
encodedMessage = [self.rest.defaultEncoder encodeMessages:data];
}

Expand Down
1 change: 1 addition & 0 deletions Source/ARTStatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef NS_ENUM(NSUInteger, ARTState) {
ARTStateInvalidArgs,
ARTStateCryptoBadPadding,
ARTStateNoClientId,
ARTStateMismatchedClientId,
ARTStateBadConnectionState,
ARTStateError = 99999
};
Expand Down
7 changes: 5 additions & 2 deletions Spec/NSObject+TestSuite.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ ART_ASSUME_NONNULL_BEGIN
/// Get argument at index from the identified instance method.
- (void)testSuite_getArgumentFrom:(SEL)selector atIndex:(NSInteger)index callback:(void (^)(id))callback;

/// Inject a block of code to the identified instance method.
- (void)testSuite_injectIntoMethod:(SEL)selector code:(void (^)(void))block;
/// Inject a block of code after the identified instance method.
- (void)testSuite_injectIntoMethodAfter:(SEL)selector code:(void (^)(void))block;

/// Inject a block of code before the identified instance method.
- (void)testSuite_injectIntoMethodBefore:(SEL)selector code:(void (^)(void))block;

ART_ASSUME_NONNULL_END

Expand Down
8 changes: 7 additions & 1 deletion Spec/NSObject+TestSuite.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ - (void)testSuite_getArgumentFrom:(SEL)selector atIndex:(NSInteger)index callbac
} error:nil];
}

- (void)testSuite_injectIntoMethod:(SEL)selector code:(void (^)(void))block {
- (void)testSuite_injectIntoMethodBefore:(SEL)selector code:(void (^)(void))block {
[self aspect_hookSelector:selector withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info) {
block();
} error:nil];
}

- (void)testSuite_injectIntoMethodAfter:(SEL)selector code:(void (^)(void))block {
[self aspect_hookSelector:selector withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> info) {
block();
} error:nil];
Expand Down
6 changes: 3 additions & 3 deletions Spec/RealtimeClientChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,18 @@ class RealtimeClientChannel: QuickSpec {
expect(channel.statesEventEmitter).to(beAKindOf(ARTEventEmitter.self))

var channelOnMethodCalled = false
channel.testSuite_injectIntoMethod(#selector(ARTEventEmitter.on(_:))) {
channel.testSuite_injectIntoMethodAfter(#selector(ARTEventEmitter.on(_:))) {
channelOnMethodCalled = true
}

// The `channel.on` should use `statesEventEmitter`
var statesEventEmitterOnMethodCalled = false
channel.statesEventEmitter.testSuite_injectIntoMethod(#selector(ARTEventEmitter.on(_:))) {
channel.statesEventEmitter.testSuite_injectIntoMethodAfter(#selector(ARTEventEmitter.on(_:))) {
statesEventEmitterOnMethodCalled = true
}

var emitCounter = 0
channel.statesEventEmitter.testSuite_injectIntoMethod(#selector(ARTEventEmitter.emit(_:with:))) {
channel.statesEventEmitter.testSuite_injectIntoMethodAfter(#selector(ARTEventEmitter.emit(_:with:))) {
emitCounter += 1
}

Expand Down
30 changes: 30 additions & 0 deletions Spec/RestClientChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,37 @@ class RestClientChannel: QuickSpec {
}
}
}

// RSL1g4
pending("when publishing a Message with an explicit clientId that is incompatible with the identified client’s clientId") {
let options = AblyTests.commonAppSetup()
options.clientId = "john"
let client = ARTRest(options: options)
client.httpExecutor = mockExecutor
let channel = client.channels.get("test")

// Reject before the message is sent to the server
channel.testSuite_injectIntoMethodBefore("publish:callback:") {
mockExecutor.http = nil
}

waitUntil(timeout: testTimeout) { done in
let message = ARTMessage(name: nil, data: "message", clientId: "tester")
channel.publish([message]) { error in
expect(error!.code).to(equal(Int(ARTState.MismatchedClientId.rawValue)))

mockExecutor.http = ARTHttp()
channel.history { page, error in
expect(error).to(beNil())
expect(page!.items).to(haveCount(0))
done()
}
}
}
}

}

}

// RSL3, RSP1
Expand Down
35 changes: 20 additions & 15 deletions Spec/TestUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -497,32 +497,37 @@ func extractBodyAsMessages(request: NSMutableURLRequest?) -> Result<[NSDictionar


/// Records each request and response for test purpose.
@objc
class MockHTTPExecutor: NSObject, ARTHTTPExecutor {
// Who executes the request
private let executor = ARTHttp()


var http: ARTHttp? = ARTHttp()
var logger: ARTLog?

var requests: [NSMutableURLRequest] = []
var responses: [NSHTTPURLResponse] = []

var beforeRequest: Optional<(NSMutableURLRequest)->()> = nil
var beforeProcessingDataResponse: Optional<(NSData?)->(NSData)> = nil

func executeRequest(request: NSMutableURLRequest, completion callback: ((NSHTTPURLResponse?, NSData?, NSError?) -> Void)?) {
self.requests.append(request)
self.executor.executeRequest(request, completion: { response, data, error in
if let httpResponse = response {
self.responses.append(httpResponse)
}
if let performEvent = self.beforeProcessingDataResponse {
callback?(response, performEvent(data), error)
}
else {
callback?(response, data, error)
}
})
if let performEvent = beforeRequest {
performEvent(request)
}
if let http = self.http {
http.executeRequest(request, completion: { response, data, error in
if let httpResponse = response {
self.responses.append(httpResponse)
}
if let performEvent = self.beforeProcessingDataResponse {
callback?(response, performEvent(data), error)
}
else {
callback?(response, data, error)
}
})
}
}

}

/// Records each message for test purpose.
Expand Down