tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ARDAppClient_xctest.mm (11387B)


      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 #import <XCTest/XCTest.h>
     15 
     16 #include "rtc_base/ssl_adapter.h"
     17 
     18 #import "sdk/objc/api/peerconnection/RTCMediaConstraints.h"
     19 #import "sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h"
     20 
     21 #import "ARDAppClient+Internal.h"
     22 #import "ARDJoinResponse+Internal.h"
     23 #import "ARDMessageResponse+Internal.h"
     24 #import "ARDSettingsModel.h"
     25 
     26 @interface ARDAppClientTest : XCTestCase
     27 @end
     28 
     29 @implementation ARDAppClientTest
     30 
     31 #pragma mark - Mock helpers
     32 
     33 - (id)mockRoomServerClientForRoomId:(NSString *)roomId
     34                           clientId:(NSString *)clientId
     35                        isInitiator:(BOOL)isInitiator
     36                           messages:(NSArray *)messages
     37                     messageHandler:
     38                         (void (^)(ARDSignalingMessage *))messageHandler {
     39  id mockRoomServerClient =
     40      [OCMockObject mockForProtocol:@protocol(ARDRoomServerClient)];
     41 
     42  // Successful join response.
     43  ARDJoinResponse *joinResponse = [[ARDJoinResponse alloc] init];
     44  joinResponse.result = kARDJoinResultTypeSuccess;
     45  joinResponse.roomId = roomId;
     46  joinResponse.clientId = clientId;
     47  joinResponse.isInitiator = isInitiator;
     48  joinResponse.messages = messages;
     49 
     50  // Successful message response.
     51  ARDMessageResponse *messageResponse = [[ARDMessageResponse alloc] init];
     52  messageResponse.result = kARDMessageResultTypeSuccess;
     53 
     54  // Return join response from above on join.
     55  [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
     56    __unsafe_unretained void (^completionHandler)(ARDJoinResponse *response,
     57                                                  NSError *error);
     58    [invocation getArgument:&completionHandler atIndex:4];
     59    completionHandler(joinResponse, nil);
     60  }] joinRoomWithRoomId:roomId isLoopback:NO completionHandler:[OCMArg any]];
     61 
     62  // Return message response from above on join.
     63  [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
     64    __unsafe_unretained ARDSignalingMessage *message;
     65    __unsafe_unretained void (^completionHandler)(ARDMessageResponse *response,
     66                                                  NSError *error);
     67    [invocation getArgument:&message atIndex:2];
     68    [invocation getArgument:&completionHandler atIndex:5];
     69    messageHandler(message);
     70    completionHandler(messageResponse, nil);
     71  }] sendMessage:[OCMArg any]
     72              forRoomId:roomId
     73               clientId:clientId
     74      completionHandler:[OCMArg any]];
     75 
     76  // Do nothing on leave.
     77  [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
     78    __unsafe_unretained void (^completionHandler)(NSError *error);
     79    [invocation getArgument:&completionHandler atIndex:4];
     80    if (completionHandler) {
     81      completionHandler(nil);
     82    }
     83  }] leaveRoomWithRoomId:roomId
     84                clientId:clientId
     85       completionHandler:[OCMArg any]];
     86 
     87  return mockRoomServerClient;
     88 }
     89 
     90 - (id)mockSignalingChannelForRoomId:(NSString *)roomId
     91                           clientId:(NSString *)clientId
     92                     messageHandler:(void (^)(ARDSignalingMessage *message))
     93                                        messageHandler {
     94  id mockSignalingChannel =
     95      [OCMockObject niceMockForProtocol:@protocol(ARDSignalingChannel)];
     96  [[mockSignalingChannel stub] registerForRoomId:roomId clientId:clientId];
     97  [[[mockSignalingChannel stub] andDo:^(NSInvocation *invocation) {
     98    __unsafe_unretained ARDSignalingMessage *message;
     99    [invocation getArgument:&message atIndex:2];
    100    messageHandler(message);
    101  }] sendMessage:[OCMArg any]];
    102  return mockSignalingChannel;
    103 }
    104 
    105 - (id)mockTURNClient {
    106  id mockTURNClient = [OCMockObject mockForProtocol:@protocol(ARDTURNClient)];
    107  [[[mockTURNClient stub] andDo:^(NSInvocation *invocation) {
    108    // Don't return anything in TURN response.
    109    __unsafe_unretained void (^completionHandler)(NSArray *turnServers,
    110                                                  NSError *error);
    111    [invocation getArgument:&completionHandler atIndex:2];
    112    completionHandler([NSArray array], nil);
    113  }] requestServersWithCompletionHandler:[OCMArg any]];
    114  return mockTURNClient;
    115 }
    116 
    117 - (id)mockSettingsModel {
    118  ARDSettingsModel *model = [[ARDSettingsModel alloc] init];
    119  id partialMock = [OCMockObject partialMockForObject:model];
    120  [[[partialMock stub] andReturn:@[ @"640x480", @"960x540", @"1280x720" ]]
    121      availableVideoResolutions];
    122 
    123  return model;
    124 }
    125 
    126 - (ARDAppClient *)
    127    createAppClientForRoomId:(NSString *)roomId
    128                    clientId:(NSString *)clientId
    129                 isInitiator:(BOOL)isInitiator
    130                    messages:(NSArray *)messages
    131              messageHandler:
    132                  (void (^)(ARDSignalingMessage *message))messageHandler
    133            connectedHandler:(void (^)(void))connectedHandler
    134      localVideoTrackHandler:(void (^)(void))localVideoTrackHandler {
    135  id turnClient = [self mockTURNClient];
    136  id signalingChannel = [self mockSignalingChannelForRoomId:roomId
    137                                                   clientId:clientId
    138                                             messageHandler:messageHandler];
    139  id roomServerClient = [self mockRoomServerClientForRoomId:roomId
    140                                                   clientId:clientId
    141                                                isInitiator:isInitiator
    142                                                   messages:messages
    143                                             messageHandler:messageHandler];
    144  id delegate =
    145      [OCMockObject niceMockForProtocol:@protocol(ARDAppClientDelegate)];
    146  [[[delegate stub] andDo:^(NSInvocation *invocation) {
    147    connectedHandler();
    148  }] appClient:[OCMArg any]
    149      didChangeConnectionState:RTCIceConnectionStateConnected];
    150  [[[delegate stub] andDo:^(NSInvocation *invocation) {
    151    localVideoTrackHandler();
    152  }] appClient:[OCMArg any] didReceiveLocalVideoTrack:[OCMArg any]];
    153 
    154  return [[ARDAppClient alloc] initWithRoomServerClient:roomServerClient
    155                                       signalingChannel:signalingChannel
    156                                             turnClient:turnClient
    157                                               delegate:delegate];
    158 }
    159 
    160 #pragma mark - Cases
    161 
    162 // Tests that an ICE connection is established between two ARDAppClient objects
    163 // where one is set up as a caller and the other the answerer. Network
    164 // components are mocked out and messages are relayed directly from object to
    165 // object. It's expected that both clients reach the
    166 // RTCIceConnectionStateConnected state within a reasonable amount of time.
    167 - (void)testSession {
    168  // Need block arguments here because we're setting up a callbacks before we
    169  // create the clients.
    170  ARDAppClient *caller = nil;
    171  ARDAppClient *answerer = nil;
    172  __block __weak ARDAppClient *weakCaller = nil;
    173  __block __weak ARDAppClient *weakAnswerer = nil;
    174  NSString *roomId = @"testRoom";
    175  NSString *callerId = @"testCallerId";
    176  NSString *answererId = @"testAnswererId";
    177 
    178  XCTestExpectation *callerConnectionExpectation =
    179      [self expectationWithDescription:@"Caller PC connected"];
    180  XCTestExpectation *answererConnectionExpectation =
    181      [self expectationWithDescription:@"Answerer PC connected"];
    182 
    183  caller = [self createAppClientForRoomId:roomId
    184      clientId:callerId
    185      isInitiator:YES
    186      messages:[NSArray array]
    187      messageHandler:^(ARDSignalingMessage *message) {
    188        ARDAppClient *strongAnswerer = weakAnswerer;
    189        [strongAnswerer channel:strongAnswerer.channel
    190              didReceiveMessage:message];
    191      }
    192      connectedHandler:^{
    193        [callerConnectionExpectation fulfill];
    194      }
    195      localVideoTrackHandler:^{
    196      }];
    197  // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion
    198  // crash in Debug.
    199  caller.defaultPeerConnectionConstraints = [[RTC_OBJC_TYPE(RTCMediaConstraints)
    200      alloc] initWithMandatoryConstraints:nil optionalConstraints:nil];
    201  weakCaller = caller;
    202 
    203  answerer = [self createAppClientForRoomId:roomId
    204      clientId:answererId
    205      isInitiator:NO
    206      messages:[NSArray array]
    207      messageHandler:^(ARDSignalingMessage *message) {
    208        ARDAppClient *strongCaller = weakCaller;
    209        [strongCaller channel:strongCaller.channel didReceiveMessage:message];
    210      }
    211      connectedHandler:^{
    212        [answererConnectionExpectation fulfill];
    213      }
    214      localVideoTrackHandler:^{
    215      }];
    216  // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion
    217  // crash in Debug.
    218  answerer.defaultPeerConnectionConstraints =
    219      [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc]
    220          initWithMandatoryConstraints:nil
    221                   optionalConstraints:nil];
    222  weakAnswerer = answerer;
    223 
    224  // Kick off connection.
    225  [caller connectToRoomWithId:roomId
    226                     settings:[self mockSettingsModel]
    227                   isLoopback:NO];
    228  [answerer connectToRoomWithId:roomId
    229                       settings:[self mockSettingsModel]
    230                     isLoopback:NO];
    231  [self waitForExpectationsWithTimeout:20
    232                               handler:^(NSError *error) {
    233                                 if (error) {
    234                                   XCTFail(@"Expectation failed with error %@.",
    235                                           error);
    236                                 }
    237                               }];
    238 }
    239 
    240 // Test to see that we get a local video connection
    241 // Note this will currently pass even when no camera is connected as a local
    242 // video track is created regardless (Perhaps there should be a test for
    243 // that...)
    244 #if !TARGET_IPHONE_SIMULATOR  // Expect to fail on simulator due to no camera
    245                              // support
    246 - (void)testSessionShouldGetLocalVideoTrackCallback {
    247  ARDAppClient *caller = nil;
    248  NSString *roomId = @"testRoom";
    249  NSString *callerId = @"testCallerId";
    250 
    251  XCTestExpectation *localVideoTrackExpectation =
    252      [self expectationWithDescription:@"Caller got local video."];
    253 
    254  caller = [self createAppClientForRoomId:roomId
    255      clientId:callerId
    256      isInitiator:YES
    257      messages:[NSArray array]
    258      messageHandler:^(ARDSignalingMessage *message) {
    259      }
    260      connectedHandler:^{
    261      }
    262      localVideoTrackHandler:^{
    263        [localVideoTrackExpectation fulfill];
    264      }];
    265  caller.defaultPeerConnectionConstraints = [[RTC_OBJC_TYPE(RTCMediaConstraints)
    266      alloc] initWithMandatoryConstraints:nil optionalConstraints:nil];
    267 
    268  // Kick off connection.
    269  [caller connectToRoomWithId:roomId
    270                     settings:[self mockSettingsModel]
    271                   isLoopback:NO];
    272  [self waitForExpectationsWithTimeout:20
    273                               handler:^(NSError *error) {
    274                                 if (error) {
    275                                   XCTFail(
    276                                       "Expectation timed out with error: %@.",
    277                                       error);
    278                                 }
    279                               }];
    280 }
    281 #endif
    282 
    283 @end