blob: 0f33bac5cc6409076d99a328ddc447bc41ac4f3b [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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}
46
47- (id)init {
48 self = [super init];
49 if (self) {
50 _expectedSignalingChanges = [NSMutableArray array];
51 _expectedSignalingChanges = [NSMutableArray array];
52 _expectedAddStreamLabels = [NSMutableArray array];
53 _expectedRemoveStreamLabels = [NSMutableArray array];
54 _receivedICECandidates = [NSMutableArray array];
55 _expectedICEConnectionChanges = [NSMutableArray array];
56 _expectedICEGatheringChanges = [NSMutableArray array];
57 }
58 return self;
59}
60
61- (int)popFirstElementAsInt:(NSMutableArray *)array {
62 NSAssert([array count] > 0, @"Empty array");
63 NSNumber *boxedState = [array objectAtIndex:0];
64 [array removeObjectAtIndex:0];
65 return [boxedState intValue];
66}
67
68- (NSString *)popFirstElementAsNSString:(NSMutableArray *)array {
69 NSAssert([array count] > 0, @"Empty expectation array");
70 NSString *string = [array objectAtIndex:0];
71 [array removeObjectAtIndex:0];
72 return string;
73}
74
75- (BOOL)areAllExpectationsSatisfied {
76 return _expectedICECandidates <= 0 && // See comment in gotICECandidate.
77 _expectedErrors == 0 &&
78 [_expectedSignalingChanges count] == 0 &&
79 [_expectedICEConnectionChanges count] == 0 &&
80 [_expectedICEGatheringChanges count] == 0 &&
81 [_expectedAddStreamLabels count] == 0 &&
82 [_expectedRemoveStreamLabels count] == 0;
83 // TODO(hughv): Test video state here too.
84}
85
86- (NSArray *)releaseReceivedICECandidates {
87 NSArray* ret = _receivedICECandidates;
88 _receivedICECandidates = [NSMutableArray array];
89 return ret;
90}
91
92- (void)expectError {
93 ++_expectedErrors;
94}
95
96- (void)expectSignalingChange:(RTCSignalingState)state {
97 [_expectedSignalingChanges addObject:@((int)state)];
98}
99
100- (void)expectAddStream:(NSString *)label {
101 [_expectedAddStreamLabels addObject:label];
102}
103
104- (void)expectRemoveStream:(NSString *)label {
105 [_expectedRemoveStreamLabels addObject:label];
106}
107
108- (void)expectICECandidates:(int)count {
109 _expectedICECandidates += count;
110}
111
112- (void)expectICEConnectionChange:(RTCICEConnectionState)state {
113 [_expectedICEConnectionChanges addObject:@((int)state)];
114}
115
116- (void)expectICEGatheringChange:(RTCICEGatheringState)state {
117 [_expectedICEGatheringChanges addObject:@((int)state)];
118}
119
120- (void)waitForAllExpectationsToBeSatisfied {
121 // TODO (fischman): Revisit. Keeping in sync with the Java version, but
122 // polling is not optimal.
123 // https://code.google.com/p/libjingle/source/browse/trunk/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java?line=212#212
124 while (![self areAllExpectationsSatisfied]) {
125 [[NSRunLoop currentRunLoop]
126 runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
127 }
128}
129
130#pragma mark - RTCPeerConnectionDelegate methods
131
132- (void)peerConnectionOnError:(RTCPeerConnection *)peerConnection {
133 NSLog(@"RTCPeerConnectionDelegate::onError");
134 NSAssert(--_expectedErrors >= 0, @"Unexpected error");
135}
136
137- (void)peerConnection:(RTCPeerConnection *)peerConnection
138 signalingStateChanged:(RTCSignalingState)stateChanged {
139 int expectedState = [self popFirstElementAsInt:_expectedSignalingChanges];
140 NSString *message = [NSString stringWithFormat: @"RTCPeerConnectionDelegate::"
141 @"onSignalingStateChange [%d] expected[%d]", stateChanged, expectedState];
142 NSAssert(expectedState == (int) stateChanged, message);
143}
144
145- (void)peerConnection:(RTCPeerConnection *)peerConnection
146 addedStream:(RTCMediaStream *)stream {
147 NSString *expectedLabel =
148 [self popFirstElementAsNSString:_expectedAddStreamLabels];
149 NSAssert([expectedLabel isEqual:stream.label], @"Stream not expected");
150}
151
152- (void)peerConnection:(RTCPeerConnection *)peerConnection
153 removedStream:(RTCMediaStream *)stream {
154 NSString *expectedLabel =
155 [self popFirstElementAsNSString:_expectedRemoveStreamLabels];
156 NSAssert([expectedLabel isEqual:stream.label], @"Stream not expected");
157}
158
159- (void)peerConnectionOnRenegotiationNeeded:
160 (RTCPeerConnection *)peerConnection {
161}
162
163- (void)peerConnection:(RTCPeerConnection *)peerConnection
164 gotICECandidate:(RTCICECandidate *)candidate {
165 --_expectedICECandidates;
166 // We don't assert expectedICECandidates >= 0 because it's hard to know
167 // how many to expect, in general. We only use expectICECandidates to
168 // assert a minimal count.
169 [_receivedICECandidates addObject:candidate];
170}
171
172- (void)peerConnection:(RTCPeerConnection *)peerConnection
173 iceGatheringChanged:(RTCICEGatheringState)newState {
174 // It's fine to get a variable number of GATHERING messages before
175 // COMPLETE fires (depending on how long the test runs) so we don't assert
176 // any particular count.
177 if (newState == RTCICEGatheringGathering) {
178 return;
179 }
180 int expectedState = [self popFirstElementAsInt:_expectedICEGatheringChanges];
181 NSAssert(expectedState == (int)newState, @"Empty expectation array");
182}
183
184- (void)peerConnection:(RTCPeerConnection *)peerConnection
185 iceConnectionChanged:(RTCICEConnectionState)newState {
186 int expectedState = [self popFirstElementAsInt:_expectedICEConnectionChanges];
187 NSAssert(expectedState == (int)newState, @"Empty expectation array");
188}
189
190@end