OLD | NEW |
| (Empty) |
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/jav
atests/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 | |
OLD | NEW |