Home | History | Annotate | Download | only in objctests
      1 /*
      2  * libjingle
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #if !defined(__has_feature) || !__has_feature(objc_arc)
     29 #error "This file requires ARC support."
     30 #endif
     31 
     32 #import "RTCPeerConnectionSyncObserver.h"
     33 
     34 #import "RTCMediaStream.h"
     35 
     36 @implementation RTCPeerConnectionSyncObserver {
     37   int _expectedErrors;
     38   NSMutableArray* _expectedSignalingChanges;
     39   NSMutableArray* _expectedAddStreamLabels;
     40   NSMutableArray* _expectedRemoveStreamLabels;
     41   int _expectedICECandidates;
     42   NSMutableArray* _receivedICECandidates;
     43   NSMutableArray* _expectedICEConnectionChanges;
     44   NSMutableArray* _expectedICEGatheringChanges;
     45   NSMutableArray* _expectedDataChannels;
     46   NSMutableArray* _expectedStateChanges;
     47   NSMutableArray* _expectedMessages;
     48 }
     49 
     50 - (id)init {
     51   self = [super init];
     52   if (self) {
     53     _expectedSignalingChanges = [NSMutableArray array];
     54     _expectedSignalingChanges = [NSMutableArray array];
     55     _expectedAddStreamLabels = [NSMutableArray array];
     56     _expectedRemoveStreamLabels = [NSMutableArray array];
     57     _receivedICECandidates = [NSMutableArray array];
     58     _expectedICEConnectionChanges = [NSMutableArray array];
     59     _expectedICEGatheringChanges = [NSMutableArray array];
     60     _expectedDataChannels = [NSMutableArray array];
     61     _expectedMessages = [NSMutableArray array];
     62     _expectedStateChanges = [NSMutableArray array];
     63   }
     64   return self;
     65 }
     66 
     67 - (int)popFirstElementAsInt:(NSMutableArray*)array {
     68   NSAssert([array count] > 0, @"Empty array");
     69   NSNumber* boxedState = [array objectAtIndex:0];
     70   [array removeObjectAtIndex:0];
     71   return [boxedState intValue];
     72 }
     73 
     74 - (NSString*)popFirstElementAsNSString:(NSMutableArray*)array {
     75   NSAssert([array count] > 0, @"Empty expectation array");
     76   NSString* string = [array objectAtIndex:0];
     77   [array removeObjectAtIndex:0];
     78   return string;
     79 }
     80 
     81 - (BOOL)areAllExpectationsSatisfied {
     82   return _expectedICECandidates <= 0 &&  // See comment in gotICECandidate.
     83          _expectedErrors == 0 && [_expectedSignalingChanges count] == 0 &&
     84          [_expectedICEConnectionChanges count] == 0 &&
     85          [_expectedICEGatheringChanges count] == 0 &&
     86          [_expectedAddStreamLabels count] == 0 &&
     87          [_expectedRemoveStreamLabels count] == 0 &&
     88          [_expectedDataChannels count] == 0 &&
     89          [_expectedStateChanges count] == 0 &&
     90          [_expectedMessages count] == 0;
     91   // TODO(hughv): Test video state here too.
     92 }
     93 
     94 - (NSArray*)releaseReceivedICECandidates {
     95   NSArray* ret = _receivedICECandidates;
     96   _receivedICECandidates = [NSMutableArray array];
     97   return ret;
     98 }
     99 
    100 - (void)expectError {
    101   ++_expectedErrors;
    102 }
    103 
    104 - (void)expectSignalingChange:(RTCSignalingState)state {
    105   [_expectedSignalingChanges addObject:@((int)state)];
    106 }
    107 
    108 - (void)expectAddStream:(NSString*)label {
    109   [_expectedAddStreamLabels addObject:label];
    110 }
    111 
    112 - (void)expectRemoveStream:(NSString*)label {
    113   [_expectedRemoveStreamLabels addObject:label];
    114 }
    115 
    116 - (void)expectICECandidates:(int)count {
    117   _expectedICECandidates += count;
    118 }
    119 
    120 - (void)expectICEConnectionChange:(RTCICEConnectionState)state {
    121   [_expectedICEConnectionChanges addObject:@((int)state)];
    122 }
    123 
    124 - (void)expectICEGatheringChange:(RTCICEGatheringState)state {
    125   [_expectedICEGatheringChanges addObject:@((int)state)];
    126 }
    127 
    128 - (void)expectDataChannel:(NSString*)label {
    129   [_expectedDataChannels addObject:label];
    130 }
    131 
    132 - (void)expectStateChange:(RTCDataChannelState)state {
    133   [_expectedStateChanges addObject:@(state)];
    134 }
    135 
    136 - (void)expectMessage:(NSData*)message isBinary:(BOOL)isBinary {
    137   RTCDataBuffer* buffer = [[RTCDataBuffer alloc] initWithData:message
    138                                                      isBinary:isBinary];
    139   [_expectedMessages addObject:buffer];
    140 }
    141 
    142 - (BOOL)waitForAllExpectationsToBeSatisfiedWithTimeout:(NSTimeInterval)timeout {
    143   NSParameterAssert(timeout >= 0);
    144   // TODO (fischman):  Revisit.  Keeping in sync with the Java version, but
    145   // polling is not optimal.
    146   // https://code.google.com/p/libjingle/source/browse/trunk/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java?line=212#212
    147   NSDate *startTime = [NSDate date];
    148   while (![self areAllExpectationsSatisfied]) {
    149     if (startTime.timeIntervalSinceNow < -timeout) {
    150       return NO;
    151     }
    152     [[NSRunLoop currentRunLoop]
    153         runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    154   }
    155   return YES;
    156 }
    157 
    158 #pragma mark - RTCPeerConnectionDelegate methods
    159 
    160 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    161     signalingStateChanged:(RTCSignalingState)stateChanged {
    162   int expectedState = [self popFirstElementAsInt:_expectedSignalingChanges];
    163   NSString* message =
    164       [NSString stringWithFormat:@"RTCPeerConnectionDelegate::"
    165                                  @"onSignalingStateChange [%d] expected[%d]",
    166                                  stateChanged,
    167                                  expectedState];
    168   NSAssert(expectedState == (int)stateChanged, message);
    169 }
    170 
    171 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    172            addedStream:(RTCMediaStream*)stream {
    173   NSString* expectedLabel =
    174       [self popFirstElementAsNSString:_expectedAddStreamLabels];
    175   NSAssert([expectedLabel isEqual:stream.label], @"Stream not expected");
    176 }
    177 
    178 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    179          removedStream:(RTCMediaStream*)stream {
    180   NSString* expectedLabel =
    181       [self popFirstElementAsNSString:_expectedRemoveStreamLabels];
    182   NSAssert([expectedLabel isEqual:stream.label], @"Stream not expected");
    183 }
    184 
    185 - (void)peerConnectionOnRenegotiationNeeded:(RTCPeerConnection*)peerConnection {
    186 }
    187 
    188 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    189        gotICECandidate:(RTCICECandidate*)candidate {
    190   --_expectedICECandidates;
    191   // We don't assert expectedICECandidates >= 0 because it's hard to know
    192   // how many to expect, in general.  We only use expectICECandidates to
    193   // assert a minimal count.
    194   [_receivedICECandidates addObject:candidate];
    195 }
    196 
    197 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    198     iceGatheringChanged:(RTCICEGatheringState)newState {
    199   // It's fine to get a variable number of GATHERING messages before
    200   // COMPLETE fires (depending on how long the test runs) so we don't assert
    201   // any particular count.
    202   if (newState == RTCICEGatheringGathering) {
    203     return;
    204   }
    205   NSAssert([_expectedICEGatheringChanges count] > 0,
    206            @"Unexpected ICE gathering state change");
    207   int expectedState = [self popFirstElementAsInt:_expectedICEGatheringChanges];
    208   NSAssert(expectedState == (int)newState,
    209            @"ICE gathering state should match expectation");
    210 }
    211 
    212 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    213   iceConnectionChanged:(RTCICEConnectionState)newState {
    214   // See TODO(fischman) in RTCPeerConnectionTest.mm about Completed.
    215   if (newState == RTCICEConnectionCompleted)
    216     return;
    217   NSAssert([_expectedICEConnectionChanges count] > 0,
    218            @"Unexpected ICE connection state change");
    219   int expectedState = [self popFirstElementAsInt:_expectedICEConnectionChanges];
    220   NSAssert(expectedState == (int)newState,
    221            @"ICE connection state should match expectation");
    222 }
    223 
    224 - (void)peerConnection:(RTCPeerConnection*)peerConnection
    225     didOpenDataChannel:(RTCDataChannel*)dataChannel {
    226   NSString* expectedLabel =
    227       [self popFirstElementAsNSString:_expectedDataChannels];
    228   NSAssert([expectedLabel isEqual:dataChannel.label],
    229            @"Data channel not expected");
    230   self.dataChannel = dataChannel;
    231   dataChannel.delegate = self;
    232   NSAssert(kRTCDataChannelStateConnecting == dataChannel.state,
    233            @"Unexpected state");
    234 }
    235 
    236 #pragma mark - RTCDataChannelDelegate
    237 
    238 - (void)channelDidChangeState:(RTCDataChannel*)channel {
    239   NSAssert([_expectedStateChanges count] > 0,
    240            @"Unexpected state change");
    241   int expectedState = [self popFirstElementAsInt:_expectedStateChanges];
    242   NSAssert(expectedState == channel.state, @"Channel state should match");
    243 }
    244 
    245 - (void)channel:(RTCDataChannel*)channel
    246     didChangeBufferedAmount:(NSUInteger)previousAmount {
    247   NSAssert(channel.bufferedAmount != previousAmount,
    248            @"Invalid bufferedAmount change");
    249 }
    250 
    251 - (void)channel:(RTCDataChannel*)channel
    252     didReceiveMessageWithBuffer:(RTCDataBuffer*)buffer {
    253   NSAssert([_expectedMessages count] > 0,
    254            @"Unexpected message received");
    255   RTCDataBuffer* expectedBuffer = [_expectedMessages objectAtIndex:0];
    256   NSAssert(expectedBuffer.isBinary == buffer.isBinary,
    257            @"Buffer isBinary should match");
    258   NSAssert([expectedBuffer.data isEqual:buffer.data],
    259            @"Buffer data should match");
    260   [_expectedMessages removeObjectAtIndex:0];
    261 }
    262 
    263 @end
    264