OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #import <Foundation/Foundation.h> | 11 #import <Foundation/Foundation.h> |
12 #import <QuartzCore/CoreAnimation.h> | |
tkchin_webrtc
2016/11/07 19:14:21
alphabetize
| |
12 #import <OCMock/OCMock.h> | 13 #import <OCMock/OCMock.h> |
13 | 14 |
14 #include "webrtc/base/gunit.h" | 15 #include "webrtc/base/gunit.h" |
15 #include "webrtc/base/ssladapter.h" | 16 #include "webrtc/base/ssladapter.h" |
16 | 17 |
17 #import "WebRTC/RTCMediaConstraints.h" | 18 #import "WebRTC/RTCMediaConstraints.h" |
18 #import "WebRTC/RTCPeerConnectionFactory.h" | 19 #import "WebRTC/RTCPeerConnectionFactory.h" |
19 #import "WebRTC/RTCSessionDescription.h" | 20 #import "WebRTC/RTCSessionDescription.h" |
20 | 21 |
21 #import "ARDAppClient+Internal.h" | 22 #import "ARDAppClient+Internal.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
49 | 50 |
50 - (void)fulfill { | 51 - (void)fulfill { |
51 _isFulfilled = YES; | 52 _isFulfilled = YES; |
52 } | 53 } |
53 | 54 |
54 @end | 55 @end |
55 | 56 |
56 @interface ARDTestCase : NSObject | 57 @interface ARDTestCase : NSObject |
57 | 58 |
58 - (ARDTestExpectation *)expectationWithDescription:(NSString *)description; | 59 - (ARDTestExpectation *)expectationWithDescription:(NSString *)description; |
59 - (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout | 60 - (void)waitForExpectationsWithTimeout:(CFTimeInterval)timeout |
60 handler:(void (^)(NSError *error))handler; | 61 handler:(void (^)(BOOL didError))handler; |
tkchin_webrtc
2016/11/07 19:14:21
This was meant to mirror XCTest interfaces so make
afedor
2016/11/07 20:25:25
OK, but to maintain the interface, I should also p
| |
61 | 62 |
62 @end | 63 @end |
63 | 64 |
64 @implementation ARDTestCase { | 65 @implementation ARDTestCase { |
65 NSMutableArray *_expectations; | 66 NSMutableArray *_expectations; |
66 } | 67 } |
67 | 68 |
68 - (instancetype)init { | 69 - (instancetype)init { |
69 if (self = [super init]) { | 70 if (self = [super init]) { |
70 _expectations = [NSMutableArray array]; | 71 _expectations = [NSMutableArray array]; |
71 } | 72 } |
72 return self; | 73 return self; |
73 } | 74 } |
74 | 75 |
75 - (ARDTestExpectation *)expectationWithDescription:(NSString *)description { | 76 - (ARDTestExpectation *)expectationWithDescription:(NSString *)description { |
76 ARDTestExpectation *expectation = | 77 ARDTestExpectation *expectation = |
77 [[ARDTestExpectation alloc] initWithDescription:description]; | 78 [[ARDTestExpectation alloc] initWithDescription:description]; |
78 [_expectations addObject:expectation]; | 79 [_expectations addObject:expectation]; |
79 return expectation; | 80 return expectation; |
80 } | 81 } |
81 | 82 |
82 - (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout | 83 - (void)waitForExpectationsWithTimeout:(CFTimeInterval)timeout |
83 handler:(void (^)(NSError *error))handler { | 84 handler:(void (^)(BOOL didError))handler { |
84 NSDate *startDate = [NSDate date]; | 85 CFTimeInterval startTime = CACurrentMediaTime(); |
86 BOOL didErrorExp = NO; | |
tkchin_webrtc
2016/11/07 19:14:21
CFTimeInterval change looks good, but please retur
| |
85 while (![self areExpectationsFulfilled]) { | 87 while (![self areExpectationsFulfilled]) { |
86 NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startDate]; | 88 CFTimeInterval duration = CACurrentMediaTime() - startTime; |
87 if (duration > timeout) { | 89 if (duration > timeout) { |
88 NSAssert(NO, @"Expectation timed out."); | 90 didErrorExp = YES; |
89 break; | 91 break; |
90 } | 92 } |
91 [[NSRunLoop currentRunLoop] | 93 [[NSRunLoop currentRunLoop] |
92 runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; | 94 runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; |
93 } | 95 } |
94 handler(nil); | 96 handler(didErrorExp); |
95 } | 97 } |
96 | 98 |
97 - (BOOL)areExpectationsFulfilled { | 99 - (BOOL)areExpectationsFulfilled { |
98 for (ARDTestExpectation *expectation in _expectations) { | 100 for (ARDTestExpectation *expectation in _expectations) { |
99 if (!expectation.isFulfilled) { | 101 if (!expectation.isFulfilled) { |
100 return NO; | 102 return NO; |
101 } | 103 } |
102 } | 104 } |
103 return YES; | 105 return YES; |
104 } | 106 } |
(...skipping 25 matching lines...) Expand all Loading... | |
130 joinResponse.messages = messages; | 132 joinResponse.messages = messages; |
131 | 133 |
132 // Successful message response. | 134 // Successful message response. |
133 ARDMessageResponse *messageResponse = [[ARDMessageResponse alloc] init]; | 135 ARDMessageResponse *messageResponse = [[ARDMessageResponse alloc] init]; |
134 messageResponse.result = kARDMessageResultTypeSuccess; | 136 messageResponse.result = kARDMessageResultTypeSuccess; |
135 | 137 |
136 // Return join response from above on join. | 138 // Return join response from above on join. |
137 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) { | 139 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) { |
138 __unsafe_unretained void (^completionHandler)(ARDJoinResponse *response, | 140 __unsafe_unretained void (^completionHandler)(ARDJoinResponse *response, |
139 NSError *error); | 141 NSError *error); |
140 [invocation getArgument:&completionHandler atIndex:3]; | 142 [invocation getArgument:&completionHandler atIndex:4]; |
141 completionHandler(joinResponse, nil); | 143 completionHandler(joinResponse, nil); |
142 }] joinRoomWithRoomId:roomId isLoopback:NO completionHandler:[OCMArg any]]; | 144 }] joinRoomWithRoomId:roomId isLoopback:NO completionHandler:[OCMArg any]]; |
143 | 145 |
144 // Return message response from above on join. | 146 // Return message response from above on join. |
145 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) { | 147 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) { |
146 __unsafe_unretained ARDSignalingMessage *message; | 148 __unsafe_unretained ARDSignalingMessage *message; |
147 __unsafe_unretained void (^completionHandler)(ARDMessageResponse *response, | 149 __unsafe_unretained void (^completionHandler)(ARDMessageResponse *response, |
148 NSError *error); | 150 NSError *error); |
149 [invocation getArgument:&message atIndex:2]; | 151 [invocation getArgument:&message atIndex:2]; |
150 [invocation getArgument:&completionHandler atIndex:5]; | 152 [invocation getArgument:&completionHandler atIndex:5]; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 }] requestServersWithCompletionHandler:[OCMArg any]]; | 198 }] requestServersWithCompletionHandler:[OCMArg any]]; |
197 return mockTURNClient; | 199 return mockTURNClient; |
198 } | 200 } |
199 | 201 |
200 - (ARDAppClient *)createAppClientForRoomId:(NSString *)roomId | 202 - (ARDAppClient *)createAppClientForRoomId:(NSString *)roomId |
201 clientId:(NSString *)clientId | 203 clientId:(NSString *)clientId |
202 isInitiator:(BOOL)isInitiator | 204 isInitiator:(BOOL)isInitiator |
203 messages:(NSArray *)messages | 205 messages:(NSArray *)messages |
204 messageHandler: | 206 messageHandler: |
205 (void (^)(ARDSignalingMessage *message))messageHandler | 207 (void (^)(ARDSignalingMessage *message))messageHandler |
206 connectedHandler:(void (^)(void))connectedHandler { | 208 connectedHandler:(void (^)(NSString *))connectedHandle r { |
tkchin_webrtc
2016/11/07 19:14:21
instead of passing the name of the method, just in
| |
207 id turnClient = [self mockTURNClient]; | 209 id turnClient = [self mockTURNClient]; |
208 id signalingChannel = [self mockSignalingChannelForRoomId:roomId | 210 id signalingChannel = [self mockSignalingChannelForRoomId:roomId |
209 clientId:clientId | 211 clientId:clientId |
210 messageHandler:messageHandler]; | 212 messageHandler:messageHandler]; |
211 id roomServerClient = | 213 id roomServerClient = |
212 [self mockRoomServerClientForRoomId:roomId | 214 [self mockRoomServerClientForRoomId:roomId |
213 clientId:clientId | 215 clientId:clientId |
214 isInitiator:isInitiator | 216 isInitiator:isInitiator |
215 messages:messages | 217 messages:messages |
216 messageHandler:messageHandler]; | 218 messageHandler:messageHandler]; |
217 id delegate = | 219 id delegate = |
218 [OCMockObject niceMockForProtocol:@protocol(ARDAppClientDelegate)]; | 220 [OCMockObject niceMockForProtocol:@protocol(ARDAppClientDelegate)]; |
219 [[[delegate stub] andDo:^(NSInvocation *invocation) { | 221 [[[delegate stub] andDo:^(NSInvocation *invocation) { |
220 connectedHandler(); | 222 connectedHandler(NSStringFromSelector([invocation selector])); |
221 }] appClient:[OCMArg any] | 223 }] appClient:[OCMArg any] |
222 didChangeConnectionState:RTCIceConnectionStateConnected]; | 224 didChangeConnectionState:RTCIceConnectionStateConnected]; |
225 [[[delegate stub] andDo:^(NSInvocation *invocation) { | |
226 connectedHandler(NSStringFromSelector([invocation selector])); | |
227 }] appClient:[OCMArg any] | |
228 didReceiveLocalVideoTrack:[OCMArg any]]; | |
223 | 229 |
224 return [[ARDAppClient alloc] initWithRoomServerClient:roomServerClient | 230 return [[ARDAppClient alloc] initWithRoomServerClient:roomServerClient |
225 signalingChannel:signalingChannel | 231 signalingChannel:signalingChannel |
226 turnClient:turnClient | 232 turnClient:turnClient |
227 delegate:delegate]; | 233 delegate:delegate]; |
228 } | 234 } |
229 | 235 |
230 // Tests that an ICE connection is established between two ARDAppClient objects | 236 // Tests that an ICE connection is established between two ARDAppClient objects |
231 // where one is set up as a caller and the other the answerer. Network | 237 // where one is set up as a caller and the other the answerer. Network |
232 // components are mocked out and messages are relayed directly from object to | 238 // components are mocked out and messages are relayed directly from object to |
(...skipping 15 matching lines...) Expand all Loading... | |
248 ARDTestExpectation *answererConnectionExpectation = | 254 ARDTestExpectation *answererConnectionExpectation = |
249 [self expectationWithDescription:@"Answerer PC connected."]; | 255 [self expectationWithDescription:@"Answerer PC connected."]; |
250 | 256 |
251 caller = [self createAppClientForRoomId:roomId | 257 caller = [self createAppClientForRoomId:roomId |
252 clientId:callerId | 258 clientId:callerId |
253 isInitiator:YES | 259 isInitiator:YES |
254 messages:[NSArray array] | 260 messages:[NSArray array] |
255 messageHandler:^(ARDSignalingMessage *message) { | 261 messageHandler:^(ARDSignalingMessage *message) { |
256 ARDAppClient *strongAnswerer = weakAnswerer; | 262 ARDAppClient *strongAnswerer = weakAnswerer; |
257 [strongAnswerer channel:strongAnswerer.channel didReceiveMessage:message]; | 263 [strongAnswerer channel:strongAnswerer.channel didReceiveMessage:message]; |
258 } connectedHandler:^{ | 264 } connectedHandler:^(NSString *connectedSelectorString){ |
259 [callerConnectionExpectation fulfill]; | 265 if ([connectedSelectorString |
266 isEqualToString:@"appClient:didChangeConnectionState:"]) | |
267 [callerConnectionExpectation fulfill]; | |
260 }]; | 268 }]; |
261 // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion | 269 // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion |
262 // crash in Debug. | 270 // crash in Debug. |
263 caller.defaultPeerConnectionConstraints = | 271 caller.defaultPeerConnectionConstraints = |
264 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil | 272 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil |
265 optionalConstraints:nil]; | 273 optionalConstraints:nil]; |
266 weakCaller = caller; | 274 weakCaller = caller; |
267 | 275 |
268 answerer = [self createAppClientForRoomId:roomId | 276 answerer = [self createAppClientForRoomId:roomId |
269 clientId:answererId | 277 clientId:answererId |
270 isInitiator:NO | 278 isInitiator:NO |
271 messages:[NSArray array] | 279 messages:[NSArray array] |
272 messageHandler:^(ARDSignalingMessage *message) { | 280 messageHandler:^(ARDSignalingMessage *message) { |
273 ARDAppClient *strongCaller = weakCaller; | 281 ARDAppClient *strongCaller = weakCaller; |
274 [strongCaller channel:strongCaller.channel didReceiveMessage:message]; | 282 [strongCaller channel:strongCaller.channel didReceiveMessage:message]; |
275 } connectedHandler:^{ | 283 } connectedHandler:^(NSString *connectedSelectorString){ |
276 [answererConnectionExpectation fulfill]; | 284 if ([connectedSelectorString |
285 isEqualToString:@"appClient:didChangeConnectionState:"]) | |
286 [answererConnectionExpectation fulfill]; | |
277 }]; | 287 }]; |
278 // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion | 288 // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion |
279 // crash in Debug. | 289 // crash in Debug. |
280 answerer.defaultPeerConnectionConstraints = | 290 answerer.defaultPeerConnectionConstraints = |
281 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil | 291 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil |
282 optionalConstraints:nil]; | 292 optionalConstraints:nil]; |
283 weakAnswerer = answerer; | 293 weakAnswerer = answerer; |
284 | 294 |
285 // Kick off connection. | 295 // Kick off connection. |
286 [caller connectToRoomWithId:roomId | 296 [caller connectToRoomWithId:roomId |
287 isLoopback:NO | 297 isLoopback:NO |
288 isAudioOnly:NO | 298 isAudioOnly:NO |
289 shouldMakeAecDump:NO | 299 shouldMakeAecDump:NO |
290 shouldUseLevelControl:NO]; | 300 shouldUseLevelControl:NO]; |
291 [answerer connectToRoomWithId:roomId | 301 [answerer connectToRoomWithId:roomId |
292 isLoopback:NO | 302 isLoopback:NO |
293 isAudioOnly:NO | 303 isAudioOnly:NO |
294 shouldMakeAecDump:NO | 304 shouldMakeAecDump:NO |
295 shouldUseLevelControl:NO]; | 305 shouldUseLevelControl:NO]; |
296 [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) { | 306 [self waitForExpectationsWithTimeout:20 handler:^(BOOL didError) { |
297 if (error) { | 307 if (didError) { |
298 NSLog(@"Expectations error: %@", error); | 308 EXPECT_TRUE(0); |
299 } | 309 } |
300 }]; | 310 }]; |
301 } | 311 } |
312 | |
313 // Test to see that we get a local video connection | |
314 // Note this will currently pass even when no camera is connected as a local | |
315 // video track is created regardless (Perhaps there should be a test for that... ) | |
316 - (void)testSessionShouldGetLocalVideoTrackCallback { | |
317 ARDAppClient *caller = nil; | |
318 NSString *roomId = @"testRoom"; | |
319 NSString *callerId = @"testCallerId"; | |
320 | |
321 ARDTestExpectation *callerConnectionExpectation = | |
322 [self expectationWithDescription:@"Caller PC connected."]; | |
tkchin_webrtc
2016/11/07 19:14:21
indent 4
| |
323 | |
324 caller = [self createAppClientForRoomId:roomId | |
325 clientId:callerId | |
326 isInitiator:YES | |
327 messages:[NSArray array] | |
328 messageHandler:^(ARDSignalingMessage *message) { | |
tkchin_webrtc
2016/11/07 19:14:21
please follow formatting as in other methods
do no
| |
329 } | |
330 connectedHandler:^(NSString *connectedSelectorString) { | |
331 if ([connectedSelectorString | |
332 isEqualToString:@"appClient:didReceiveLocalVideoT rack:"]) | |
333 [callerConnectionExpectation fulfill]; | |
334 }]; | |
335 caller.defaultPeerConnectionConstraints = | |
336 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil | |
tkchin_webrtc
2016/11/07 19:14:21
indent 4
| |
337 optionalConstraints:nil]; | |
338 | |
339 // Kick off connection. | |
340 [caller connectToRoomWithId:roomId | |
341 isLoopback:NO | |
342 isAudioOnly:NO | |
343 shouldMakeAecDump:NO | |
344 shouldUseLevelControl:NO]; | |
345 [self waitForExpectationsWithTimeout:20 handler:^(BOOL didError) { | |
346 if (didError) { | |
347 EXPECT_TRUE(0); | |
348 } | |
349 }]; | |
350 } | |
302 | 351 |
303 @end | 352 @end |
304 | 353 |
305 @interface ARDSDPUtilsTest : ARDTestCase | 354 @interface ARDSDPUtilsTest : ARDTestCase |
306 - (void)testPreferVideoCodec; | 355 - (void)testPreferVideoCodec; |
307 @end | 356 @end |
308 | 357 |
309 @implementation ARDSDPUtilsTest | 358 @implementation ARDSDPUtilsTest |
310 | 359 |
311 - (void)testPreferVideoCodec { | 360 - (void)testPreferVideoCodec { |
312 NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120\n" | 361 NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120\n" |
313 "a=rtpmap:120 H264/90000\n"); | 362 "a=rtpmap:120 H264/90000\n"); |
314 NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 100 116 117 96\n" | 363 NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 100 116 117 96\n" |
315 "a=rtpmap:120 H264/90000\n"); | 364 "a=rtpmap:120 H264/90000\n"); |
316 RTCSessionDescription* desc = | 365 RTCSessionDescription* desc = |
317 [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp]; | 366 [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp]; |
318 RTCSessionDescription *h264Desc = | 367 RTCSessionDescription *h264Desc = |
319 [ARDSDPUtils descriptionForDescription:desc | 368 [ARDSDPUtils descriptionForDescription:desc |
320 preferredVideoCodec:@"H264"]; | 369 preferredVideoCodec:@"H264"]; |
321 EXPECT_TRUE([h264Desc.description isEqualToString:expectedSdp]); | 370 EXPECT_TRUE([h264Desc.description rangeOfString: expectedSdp].location != NSNo tFound); |
tkchin_webrtc
2016/11/07 19:14:21
nit: no space after :
EXPECT_NE?
| |
322 } | 371 } |
323 | 372 |
324 @end | 373 @end |
325 | 374 |
326 class SignalingTest : public ::testing::Test { | 375 class SignalingTest : public ::testing::Test { |
327 protected: | 376 protected: |
328 static void SetUpTestCase() { | 377 static void SetUpTestCase() { |
329 rtc::InitializeSSL(); | 378 rtc::InitializeSSL(); |
330 } | 379 } |
331 static void TearDownTestCase() { | 380 static void TearDownTestCase() { |
332 rtc::CleanupSSL(); | 381 rtc::CleanupSSL(); |
333 } | 382 } |
334 }; | 383 }; |
335 | 384 |
336 TEST_F(SignalingTest, SessionTest) { | 385 TEST_F(SignalingTest, SessionTest) { |
337 @autoreleasepool { | 386 @autoreleasepool { |
338 ARDAppClientTest *test = [[ARDAppClientTest alloc] init]; | 387 ARDAppClientTest *test = [[ARDAppClientTest alloc] init]; |
339 [test testSession]; | 388 [test testSession]; |
340 } | 389 } |
341 } | 390 } |
342 | 391 |
392 #if !TARGET_IPHONE_SIMULATOR | |
393 // Expected fail on iOS Simulator due to no camera support | |
394 TEST_F(SignalingTest, SessionLocalVideoCallbackTest) { | |
395 @autoreleasepool { | |
396 ARDAppClientTest *test = [[ARDAppClientTest alloc] init]; | |
397 [test testSessionShouldGetLocalVideoTrackCallback]; | |
398 } | |
399 } | |
400 #endif | |
401 | |
343 TEST_F(SignalingTest, SDPTest) { | 402 TEST_F(SignalingTest, SDPTest) { |
344 @autoreleasepool { | 403 @autoreleasepool { |
345 ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init]; | 404 ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init]; |
346 [test testPreferVideoCodec]; | 405 [test testPreferVideoCodec]; |
347 } | 406 } |
348 } | 407 } |
349 | 408 |
350 | 409 int main(int argc, char **argv) { |
410 ::testing::InitGoogleTest(&argc, argv); | |
411 return RUN_ALL_TESTS(); | |
412 } | |
OLD | NEW |