Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: webrtc/examples/objc/AppRTCMobile/tests/ARDAppClientTest.mm

Issue 2697603002: Move iOS tests to XCTest from gtest. (Closed)
Patch Set: fix nits Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #import <Foundation/Foundation.h>
12 #import <OCMock/OCMock.h>
13 #import <QuartzCore/CoreAnimation.h>
14
15 #include "webrtc/base/gunit.h"
16 #include "webrtc/base/ssladapter.h"
17
18 #import "WebRTC/RTCMediaConstraints.h"
19 #import "WebRTC/RTCPeerConnectionFactory.h"
20 #import "WebRTC/RTCSessionDescription.h"
21
22 #import "ARDAppClient+Internal.h"
23 #import "ARDJoinResponse+Internal.h"
24 #import "ARDMessageResponse+Internal.h"
25 #import "ARDSDPUtils.h"
26
27 static NSString *kARDAppClientTestsDomain = @"org.webrtc.ARDAppClientTests";
28 static NSInteger kARDAppClientTestsExpectationTimeoutError = 100;
29
30 // These classes mimic XCTest APIs, to make eventual conversion to XCTest
31 // easier. Conversion will happen once XCTest is supported well on build bots.
32 @interface ARDTestExpectation : NSObject
33
34 @property(nonatomic, readonly) NSString *description;
35 @property(nonatomic, readonly) BOOL isFulfilled;
36
37 - (instancetype)initWithDescription:(NSString *)description;
38 - (void)fulfill;
39
40 @end
41
42 @implementation ARDTestExpectation
43
44 @synthesize description = _description;
45 @synthesize isFulfilled = _isFulfilled;
46
47 - (instancetype)initWithDescription:(NSString *)description {
48 if (self = [super init]) {
49 _description = description;
50 }
51 return self;
52 }
53
54 - (void)fulfill {
55 _isFulfilled = YES;
56 }
57
58 @end
59
60 @interface ARDTestCase : NSObject
61
62 - (ARDTestExpectation *)expectationWithDescription:(NSString *)description;
63 - (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout
64 handler:(void (^)(NSError *error))handler;
65
66 @end
67
68 @implementation ARDTestCase {
69 NSMutableArray *_expectations;
70 }
71
72 - (instancetype)init {
73 if (self = [super init]) {
74 _expectations = [NSMutableArray array];
75 }
76 return self;
77 }
78
79 - (ARDTestExpectation *)expectationWithDescription:(NSString *)description {
80 ARDTestExpectation *expectation =
81 [[ARDTestExpectation alloc] initWithDescription:description];
82 [_expectations addObject:expectation];
83 return expectation;
84 }
85
86 - (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout
87 handler:(void (^)(NSError *error))handler {
88 CFTimeInterval startTime = CACurrentMediaTime();
89 NSError *error = nil;
90 while (![self areExpectationsFulfilled]) {
91 CFTimeInterval duration = CACurrentMediaTime() - startTime;
92 if (duration > timeout) {
93 error = [NSError errorWithDomain:kARDAppClientTestsDomain
94 code:kARDAppClientTestsExpectationTimeoutError
95 userInfo:@{}];
96 break;
97 }
98 [[NSRunLoop currentRunLoop]
99 runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
100 }
101 handler(error);
102 }
103
104 - (BOOL)areExpectationsFulfilled {
105 for (ARDTestExpectation *expectation in _expectations) {
106 if (!expectation.isFulfilled) {
107 return NO;
108 }
109 }
110 return YES;
111 }
112
113 @end
114
115 @interface ARDAppClientTest : ARDTestCase
116 @end
117
118 @implementation ARDAppClientTest
119
120 #pragma mark - Mock helpers
121
122 - (id)mockRoomServerClientForRoomId:(NSString *)roomId
123 clientId:(NSString *)clientId
124 isInitiator:(BOOL)isInitiator
125 messages:(NSArray *)messages
126 messageHandler:
127 (void (^)(ARDSignalingMessage *))messageHandler {
128 id mockRoomServerClient =
129 [OCMockObject mockForProtocol:@protocol(ARDRoomServerClient)];
130
131 // Successful join response.
132 ARDJoinResponse *joinResponse = [[ARDJoinResponse alloc] init];
133 joinResponse.result = kARDJoinResultTypeSuccess;
134 joinResponse.roomId = roomId;
135 joinResponse.clientId = clientId;
136 joinResponse.isInitiator = isInitiator;
137 joinResponse.messages = messages;
138
139 // Successful message response.
140 ARDMessageResponse *messageResponse = [[ARDMessageResponse alloc] init];
141 messageResponse.result = kARDMessageResultTypeSuccess;
142
143 // Return join response from above on join.
144 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
145 __unsafe_unretained void (^completionHandler)(ARDJoinResponse *response,
146 NSError *error);
147 [invocation getArgument:&completionHandler atIndex:4];
148 completionHandler(joinResponse, nil);
149 }] joinRoomWithRoomId:roomId isLoopback:NO completionHandler:[OCMArg any]];
150
151 // Return message response from above on join.
152 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
153 __unsafe_unretained ARDSignalingMessage *message;
154 __unsafe_unretained void (^completionHandler)(ARDMessageResponse *response,
155 NSError *error);
156 [invocation getArgument:&message atIndex:2];
157 [invocation getArgument:&completionHandler atIndex:5];
158 messageHandler(message);
159 completionHandler(messageResponse, nil);
160 }] sendMessage:[OCMArg any]
161 forRoomId:roomId
162 clientId:clientId
163 completionHandler:[OCMArg any]];
164
165 // Do nothing on leave.
166 [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
167 __unsafe_unretained void (^completionHandler)(NSError *error);
168 [invocation getArgument:&completionHandler atIndex:4];
169 if (completionHandler) {
170 completionHandler(nil);
171 }
172 }] leaveRoomWithRoomId:roomId
173 clientId:clientId
174 completionHandler:[OCMArg any]];
175
176 return mockRoomServerClient;
177 }
178
179 - (id)mockSignalingChannelForRoomId:(NSString *)roomId
180 clientId:(NSString *)clientId
181 messageHandler:
182 (void (^)(ARDSignalingMessage *message))messageHandler {
183 id mockSignalingChannel =
184 [OCMockObject niceMockForProtocol:@protocol(ARDSignalingChannel)];
185 [[mockSignalingChannel stub] registerForRoomId:roomId clientId:clientId];
186 [[[mockSignalingChannel stub] andDo:^(NSInvocation *invocation) {
187 __unsafe_unretained ARDSignalingMessage *message;
188 [invocation getArgument:&message atIndex:2];
189 messageHandler(message);
190 }] sendMessage:[OCMArg any]];
191 return mockSignalingChannel;
192 }
193
194 - (id)mockTURNClient {
195 id mockTURNClient =
196 [OCMockObject mockForProtocol:@protocol(ARDTURNClient)];
197 [[[mockTURNClient stub] andDo:^(NSInvocation *invocation) {
198 // Don't return anything in TURN response.
199 __unsafe_unretained void (^completionHandler)(NSArray *turnServers,
200 NSError *error);
201 [invocation getArgument:&completionHandler atIndex:2];
202 completionHandler([NSArray array], nil);
203 }] requestServersWithCompletionHandler:[OCMArg any]];
204 return mockTURNClient;
205 }
206
207 - (ARDAppClient *)createAppClientForRoomId:(NSString *)roomId
208 clientId:(NSString *)clientId
209 isInitiator:(BOOL)isInitiator
210 messages:(NSArray *)messages
211 messageHandler:
212 (void (^)(ARDSignalingMessage *message))messageHandler
213 connectedHandler:(void (^)(void))connectedHandler
214 localVideoTrackHandler:(void (^)(void))localVideoTrackHandle r {
215 id turnClient = [self mockTURNClient];
216 id signalingChannel = [self mockSignalingChannelForRoomId:roomId
217 clientId:clientId
218 messageHandler:messageHandler];
219 id roomServerClient =
220 [self mockRoomServerClientForRoomId:roomId
221 clientId:clientId
222 isInitiator:isInitiator
223 messages:messages
224 messageHandler:messageHandler];
225 id delegate =
226 [OCMockObject niceMockForProtocol:@protocol(ARDAppClientDelegate)];
227 [[[delegate stub] andDo:^(NSInvocation *invocation) {
228 connectedHandler();
229 }] appClient:[OCMArg any]
230 didChangeConnectionState:RTCIceConnectionStateConnected];
231 [[[delegate stub] andDo:^(NSInvocation *invocation) {
232 localVideoTrackHandler();
233 }] appClient:[OCMArg any]
234 didReceiveLocalVideoTrack:[OCMArg any]];
235
236 return [[ARDAppClient alloc] initWithRoomServerClient:roomServerClient
237 signalingChannel:signalingChannel
238 turnClient:turnClient
239 delegate:delegate];
240 }
241
242 // Tests that an ICE connection is established between two ARDAppClient objects
243 // where one is set up as a caller and the other the answerer. Network
244 // components are mocked out and messages are relayed directly from object to
245 // object. It's expected that both clients reach the
246 // RTCIceConnectionStateConnected state within a reasonable amount of time.
247 - (void)testSession {
248 // Need block arguments here because we're setting up a callbacks before we
249 // create the clients.
250 ARDAppClient *caller = nil;
251 ARDAppClient *answerer = nil;
252 __block __weak ARDAppClient *weakCaller = nil;
253 __block __weak ARDAppClient *weakAnswerer = nil;
254 NSString *roomId = @"testRoom";
255 NSString *callerId = @"testCallerId";
256 NSString *answererId = @"testAnswererId";
257
258 ARDTestExpectation *callerConnectionExpectation =
259 [self expectationWithDescription:@"Caller PC connected."];
260 ARDTestExpectation *answererConnectionExpectation =
261 [self expectationWithDescription:@"Answerer PC connected."];
262
263 caller = [self createAppClientForRoomId:roomId
264 clientId:callerId
265 isInitiator:YES
266 messages:[NSArray array]
267 messageHandler:^(ARDSignalingMessage *message) {
268 ARDAppClient *strongAnswerer = weakAnswerer;
269 [strongAnswerer channel:strongAnswerer.channel didReceiveMessage:message];
270 } connectedHandler:^{
271 [callerConnectionExpectation fulfill];
272 } localVideoTrackHandler:^{
273 }];
274 // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion
275 // crash in Debug.
276 caller.defaultPeerConnectionConstraints =
277 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
278 optionalConstraints:nil];
279 weakCaller = caller;
280
281 answerer = [self createAppClientForRoomId:roomId
282 clientId:answererId
283 isInitiator:NO
284 messages:[NSArray array]
285 messageHandler:^(ARDSignalingMessage *message) {
286 ARDAppClient *strongCaller = weakCaller;
287 [strongCaller channel:strongCaller.channel didReceiveMessage:message];
288 } connectedHandler:^{
289 [answererConnectionExpectation fulfill];
290 } localVideoTrackHandler:^{
291 }];
292 // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion
293 // crash in Debug.
294 answerer.defaultPeerConnectionConstraints =
295 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
296 optionalConstraints:nil];
297 weakAnswerer = answerer;
298
299 // Kick off connection.
300 [caller connectToRoomWithId:roomId
301 isLoopback:NO
302 isAudioOnly:NO
303 shouldMakeAecDump:NO
304 shouldUseLevelControl:NO];
305 [answerer connectToRoomWithId:roomId
306 isLoopback:NO
307 isAudioOnly:NO
308 shouldMakeAecDump:NO
309 shouldUseLevelControl:NO];
310 [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) {
311 if (error) {
312 EXPECT_TRUE(0);
313 }
314 }];
315 }
316
317 // Test to see that we get a local video connection
318 // Note this will currently pass even when no camera is connected as a local
319 // video track is created regardless (Perhaps there should be a test for that... )
320 - (void)testSessionShouldGetLocalVideoTrackCallback {
321 ARDAppClient *caller = nil;
322 NSString *roomId = @"testRoom";
323 NSString *callerId = @"testCallerId";
324
325 ARDTestExpectation *localVideoTrackExpectation =
326 [self expectationWithDescription:@"Caller got local video."];
327
328 caller = [self createAppClientForRoomId:roomId
329 clientId:callerId
330 isInitiator:YES
331 messages:[NSArray array]
332 messageHandler:^(ARDSignalingMessage *message) {
333 } connectedHandler:^{
334 } localVideoTrackHandler:^{
335 [localVideoTrackExpectation fulfill];
336 }];
337 caller.defaultPeerConnectionConstraints =
338 [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
339 optionalConstraints:nil];
340
341 // Kick off connection.
342 [caller connectToRoomWithId:roomId
343 isLoopback:NO
344 isAudioOnly:NO
345 shouldMakeAecDump:NO
346 shouldUseLevelControl:NO];
347 [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) {
348 if (error) {
349 EXPECT_TRUE(0);
350 }
351 }];
352 }
353
354 @end
355
356 @interface ARDSDPUtilsTest : ARDTestCase
357 - (void)testPreferVideoCodec:(NSString *)codec
358 sdp:(NSString *)sdp
359 expectedSdp:(NSString *)expectedSdp;
360 @end
361
362 @implementation ARDSDPUtilsTest
363
364 - (void)testPreferVideoCodec:(NSString *)codec
365 sdp:(NSString *)sdp
366 expectedSdp:(NSString *)expectedSdp {
367 RTCSessionDescription* desc =
368 [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp];
369 RTCSessionDescription *outputDesc =
370 [ARDSDPUtils descriptionForDescription:desc
371 preferredVideoCodec:codec];
372 EXPECT_TRUE([outputDesc.description rangeOfString:expectedSdp].location !=
373 NSNotFound);
374 }
375
376 @end
377
378 class SignalingTest : public ::testing::Test {
379 protected:
380 static void SetUpTestCase() {
381 rtc::InitializeSSL();
382 }
383 static void TearDownTestCase() {
384 rtc::CleanupSSL();
385 }
386 };
387
388 TEST_F(SignalingTest, SessionTest) {
389 @autoreleasepool {
390 ARDAppClientTest *test = [[ARDAppClientTest alloc] init];
391 [test testSession];
392 }
393 }
394
395 #if !TARGET_IPHONE_SIMULATOR
396 // Expected fail on iOS Simulator due to no camera support
397 TEST_F(SignalingTest, SessionLocalVideoCallbackTest) {
398 @autoreleasepool {
399 ARDAppClientTest *test = [[ARDAppClientTest alloc] init];
400 [test testSessionShouldGetLocalVideoTrackCallback];
401 }
402 }
403 #endif
404
405 TEST_F(SignalingTest, SdpH264Test) {
406 @autoreleasepool {
407 ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
408 NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n"
409 "a=rtpmap:120 H264/90000\n"
410 "a=rtpmap:97 H264/90000\n");
411 NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 97 100 116 117 96\n"
412 "a=rtpmap:120 H264/90000\n"
413 "a=rtpmap:97 H264/90000\n");
414 [test testPreferVideoCodec:@"H264"
415 sdp:sdp
416 expectedSdp:expectedSdp];
417 }
418 }
419
420 TEST_F(SignalingTest, SdpVp8Test) {
421 @autoreleasepool {
422 ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
423 NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n"
424 "a=rtpmap:116 VP8/90000\n");
425 NSString *expectedSdp = @("m=video 9 RTP/SAVPF 116 100 117 96 120 97\n"
426 "a=rtpmap:116 VP8/90000\n");
427 [test testPreferVideoCodec:@"VP8"
428 sdp:sdp
429 expectedSdp:expectedSdp];
430 }
431 }
432
433 TEST_F(SignalingTest, SdpNoMLineTest) {
434 @autoreleasepool {
435 ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
436 NSString *sdp = @("a=rtpmap:116 VP8/90000\n");
437 [test testPreferVideoCodec:@"VP8"
438 sdp:sdp
439 expectedSdp:sdp];
440 }
441 }
442
443 TEST_F(SignalingTest, SdpMissingCodecTest) {
444 @autoreleasepool {
445 ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
446 NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n"
447 "a=rtpmap:116 VP8/90000\n");
448 [test testPreferVideoCodec:@"foo"
449 sdp:sdp
450 expectedSdp:sdp];
451 }
452 }
453
454 int main(int argc, char **argv) {
455 ::testing::InitGoogleTest(&argc, argv);
456 return RUN_ALL_TESTS();
457 }
OLDNEW
« no previous file with comments | « webrtc/examples/BUILD.gn ('k') | webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698