1/* 2 * Copyright 2018 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 "api/peerconnection/RTCAudioSource.h" 12#import "api/peerconnection/RTCConfiguration.h" 13#import "api/peerconnection/RTCDataChannel.h" 14#import "api/peerconnection/RTCDataChannelConfiguration.h" 15#import "api/peerconnection/RTCMediaConstraints.h" 16#import "api/peerconnection/RTCMediaStreamTrack.h" 17#import "api/peerconnection/RTCPeerConnection.h" 18#import "api/peerconnection/RTCPeerConnectionFactory.h" 19#import "api/peerconnection/RTCRtpReceiver.h" 20#import "api/peerconnection/RTCRtpSender.h" 21#import "api/peerconnection/RTCRtpTransceiver.h" 22#import "api/peerconnection/RTCSessionDescription.h" 23#import "api/peerconnection/RTCVideoSource.h" 24#import "rtc_base/system/unused.h" 25 26#import <XCTest/XCTest.h> 27 28@interface RTCPeerConnectionFactoryTests : XCTestCase 29@end 30 31@implementation RTCPeerConnectionFactoryTests 32 33- (void)testPeerConnectionLifetime { 34 @autoreleasepool { 35 RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init]; 36 37 RTC_OBJC_TYPE(RTCMediaConstraints) *constraints = 38 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{} 39 optionalConstraints:nil]; 40 41 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 42 RTC_OBJC_TYPE(RTCPeerConnection) * peerConnection; 43 44 @autoreleasepool { 45 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 46 peerConnection = 47 [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil]; 48 [peerConnection close]; 49 factory = nil; 50 } 51 peerConnection = nil; 52 } 53 54 XCTAssertTrue(true, @"Expect test does not crash"); 55} 56 57- (void)testMediaStreamLifetime { 58 @autoreleasepool { 59 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 60 RTC_OBJC_TYPE(RTCMediaStream) * mediaStream; 61 62 @autoreleasepool { 63 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 64 mediaStream = [factory mediaStreamWithStreamId:@"mediaStream"]; 65 factory = nil; 66 } 67 mediaStream = nil; 68 RTC_UNUSED(mediaStream); 69 } 70 71 XCTAssertTrue(true, "Expect test does not crash"); 72} 73 74- (void)testDataChannelLifetime { 75 @autoreleasepool { 76 RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init]; 77 RTC_OBJC_TYPE(RTCMediaConstraints) *constraints = 78 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{} 79 optionalConstraints:nil]; 80 RTC_OBJC_TYPE(RTCDataChannelConfiguration) *dataChannelConfig = 81 [[RTC_OBJC_TYPE(RTCDataChannelConfiguration) alloc] init]; 82 83 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 84 RTC_OBJC_TYPE(RTCPeerConnection) * peerConnection; 85 RTC_OBJC_TYPE(RTCDataChannel) * dataChannel; 86 87 @autoreleasepool { 88 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 89 peerConnection = 90 [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil]; 91 dataChannel = 92 [peerConnection dataChannelForLabel:@"test_channel" configuration:dataChannelConfig]; 93 XCTAssertNotNil(dataChannel); 94 [peerConnection close]; 95 peerConnection = nil; 96 factory = nil; 97 } 98 dataChannel = nil; 99 } 100 101 XCTAssertTrue(true, "Expect test does not crash"); 102} 103 104- (void)testRTCRtpTransceiverLifetime { 105 @autoreleasepool { 106 RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init]; 107 config.sdpSemantics = RTCSdpSemanticsUnifiedPlan; 108 RTC_OBJC_TYPE(RTCMediaConstraints) *contraints = 109 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{} 110 optionalConstraints:nil]; 111 RTC_OBJC_TYPE(RTCRtpTransceiverInit) *init = 112 [[RTC_OBJC_TYPE(RTCRtpTransceiverInit) alloc] init]; 113 114 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 115 RTC_OBJC_TYPE(RTCPeerConnection) * peerConnection; 116 RTC_OBJC_TYPE(RTCRtpTransceiver) * tranceiver; 117 118 @autoreleasepool { 119 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 120 peerConnection = 121 [factory peerConnectionWithConfiguration:config constraints:contraints delegate:nil]; 122 tranceiver = [peerConnection addTransceiverOfType:RTCRtpMediaTypeAudio init:init]; 123 XCTAssertNotNil(tranceiver); 124 [peerConnection close]; 125 peerConnection = nil; 126 factory = nil; 127 } 128 tranceiver = nil; 129 } 130 131 XCTAssertTrue(true, "Expect test does not crash"); 132} 133 134- (void)testRTCRtpSenderLifetime { 135 @autoreleasepool { 136 RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init]; 137 config.sdpSemantics = RTCSdpSemanticsPlanB; 138 RTC_OBJC_TYPE(RTCMediaConstraints) *constraints = 139 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{} 140 optionalConstraints:nil]; 141 142 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 143 RTC_OBJC_TYPE(RTCPeerConnection) * peerConnection; 144 RTC_OBJC_TYPE(RTCRtpSender) * sender; 145 146 @autoreleasepool { 147 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 148 peerConnection = 149 [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil]; 150 sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo streamId:@"stream"]; 151 XCTAssertNotNil(sender); 152 [peerConnection close]; 153 peerConnection = nil; 154 factory = nil; 155 } 156 sender = nil; 157 } 158 159 XCTAssertTrue(true, "Expect test does not crash"); 160} 161 162- (void)testRTCRtpReceiverLifetime { 163 @autoreleasepool { 164 RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init]; 165 config.sdpSemantics = RTCSdpSemanticsPlanB; 166 RTC_OBJC_TYPE(RTCMediaConstraints) *constraints = 167 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{} 168 optionalConstraints:nil]; 169 170 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 171 RTC_OBJC_TYPE(RTCPeerConnection) * pc1; 172 RTC_OBJC_TYPE(RTCPeerConnection) * pc2; 173 174 NSArray<RTC_OBJC_TYPE(RTCRtpReceiver) *> *receivers1; 175 NSArray<RTC_OBJC_TYPE(RTCRtpReceiver) *> *receivers2; 176 177 @autoreleasepool { 178 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 179 pc1 = [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil]; 180 [pc1 senderWithKind:kRTCMediaStreamTrackKindAudio streamId:@"stream"]; 181 182 pc2 = [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil]; 183 [pc2 senderWithKind:kRTCMediaStreamTrackKindAudio streamId:@"stream"]; 184 185 NSTimeInterval negotiationTimeout = 15; 186 XCTAssertTrue([self negotiatePeerConnection:pc1 187 withPeerConnection:pc2 188 negotiationTimeout:negotiationTimeout]); 189 190 XCTAssertEqual(pc1.signalingState, RTCSignalingStateStable); 191 XCTAssertEqual(pc2.signalingState, RTCSignalingStateStable); 192 193 receivers1 = pc1.receivers; 194 receivers2 = pc2.receivers; 195 XCTAssertTrue(receivers1.count > 0); 196 XCTAssertTrue(receivers2.count > 0); 197 [pc1 close]; 198 [pc2 close]; 199 pc1 = nil; 200 pc2 = nil; 201 factory = nil; 202 } 203 receivers1 = nil; 204 receivers2 = nil; 205 } 206 207 XCTAssertTrue(true, "Expect test does not crash"); 208} 209 210- (void)testAudioSourceLifetime { 211 @autoreleasepool { 212 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 213 RTC_OBJC_TYPE(RTCAudioSource) * audioSource; 214 215 @autoreleasepool { 216 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 217 audioSource = [factory audioSourceWithConstraints:nil]; 218 XCTAssertNotNil(audioSource); 219 factory = nil; 220 } 221 audioSource = nil; 222 } 223 224 XCTAssertTrue(true, "Expect test does not crash"); 225} 226 227- (void)testVideoSourceLifetime { 228 @autoreleasepool { 229 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 230 RTC_OBJC_TYPE(RTCVideoSource) * videoSource; 231 232 @autoreleasepool { 233 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 234 videoSource = [factory videoSource]; 235 XCTAssertNotNil(videoSource); 236 factory = nil; 237 } 238 videoSource = nil; 239 } 240 241 XCTAssertTrue(true, "Expect test does not crash"); 242} 243 244- (void)testAudioTrackLifetime { 245 @autoreleasepool { 246 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 247 RTC_OBJC_TYPE(RTCAudioTrack) * audioTrack; 248 249 @autoreleasepool { 250 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 251 audioTrack = [factory audioTrackWithTrackId:@"audioTrack"]; 252 XCTAssertNotNil(audioTrack); 253 factory = nil; 254 } 255 audioTrack = nil; 256 } 257 258 XCTAssertTrue(true, "Expect test does not crash"); 259} 260 261- (void)testVideoTrackLifetime { 262 @autoreleasepool { 263 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 264 RTC_OBJC_TYPE(RTCVideoTrack) * videoTrack; 265 266 @autoreleasepool { 267 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 268 videoTrack = [factory videoTrackWithSource:[factory videoSource] trackId:@"videoTrack"]; 269 XCTAssertNotNil(videoTrack); 270 factory = nil; 271 } 272 videoTrack = nil; 273 } 274 275 XCTAssertTrue(true, "Expect test does not crash"); 276} 277 278- (void)testRollback { 279 @autoreleasepool { 280 RTC_OBJC_TYPE(RTCConfiguration) *config = [[RTC_OBJC_TYPE(RTCConfiguration) alloc] init]; 281 config.sdpSemantics = RTCSdpSemanticsUnifiedPlan; 282 RTC_OBJC_TYPE(RTCMediaConstraints) *constraints = 283 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{ 284 kRTCMediaConstraintsOfferToReceiveAudio : kRTCMediaConstraintsValueTrue 285 } 286 optionalConstraints:nil]; 287 288 __block RTC_OBJC_TYPE(RTCPeerConnectionFactory) * factory; 289 __block RTC_OBJC_TYPE(RTCPeerConnection) * pc1; 290 RTCSessionDescription *rollback = [[RTCSessionDescription alloc] initWithType:RTCSdpTypeRollback 291 sdp:@""]; 292 293 @autoreleasepool { 294 factory = [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init]; 295 pc1 = [factory peerConnectionWithConfiguration:config constraints:constraints delegate:nil]; 296 dispatch_semaphore_t negotiatedSem = dispatch_semaphore_create(0); 297 [pc1 offerForConstraints:constraints 298 completionHandler:^(RTC_OBJC_TYPE(RTCSessionDescription) * offer, NSError * error) { 299 XCTAssertNil(error); 300 XCTAssertNotNil(offer); 301 302 __weak RTC_OBJC_TYPE(RTCPeerConnection) *weakPC1 = pc1; 303 [pc1 setLocalDescription:offer 304 completionHandler:^(NSError *error) { 305 XCTAssertNil(error); 306 [weakPC1 setLocalDescription:rollback 307 completionHandler:^(NSError *error) { 308 XCTAssertNil(error); 309 }]; 310 }]; 311 NSTimeInterval negotiationTimeout = 15; 312 dispatch_semaphore_wait( 313 negotiatedSem, 314 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(negotiationTimeout * NSEC_PER_SEC))); 315 316 XCTAssertEqual(pc1.signalingState, RTCSignalingStateStable); 317 318 [pc1 close]; 319 pc1 = nil; 320 factory = nil; 321 }]; 322 } 323 324 XCTAssertTrue(true, "Expect test does not crash"); 325 } 326} 327 328- (bool)negotiatePeerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)pc1 329 withPeerConnection:(RTC_OBJC_TYPE(RTCPeerConnection) *)pc2 330 negotiationTimeout:(NSTimeInterval)timeout { 331 __weak RTC_OBJC_TYPE(RTCPeerConnection) *weakPC1 = pc1; 332 __weak RTC_OBJC_TYPE(RTCPeerConnection) *weakPC2 = pc2; 333 RTC_OBJC_TYPE(RTCMediaConstraints) *sdpConstraints = 334 [[RTC_OBJC_TYPE(RTCMediaConstraints) alloc] initWithMandatoryConstraints:@{ 335 kRTCMediaConstraintsOfferToReceiveAudio : kRTCMediaConstraintsValueTrue 336 } 337 optionalConstraints:nil]; 338 339 dispatch_semaphore_t negotiatedSem = dispatch_semaphore_create(0); 340 [weakPC1 offerForConstraints:sdpConstraints 341 completionHandler:^(RTC_OBJC_TYPE(RTCSessionDescription) * offer, NSError * error) { 342 XCTAssertNil(error); 343 XCTAssertNotNil(offer); 344 [weakPC1 345 setLocalDescription:offer 346 completionHandler:^(NSError *error) { 347 XCTAssertNil(error); 348 [weakPC2 349 setRemoteDescription:offer 350 completionHandler:^(NSError *error) { 351 XCTAssertNil(error); 352 [weakPC2 353 answerForConstraints:sdpConstraints 354 completionHandler:^( 355 RTC_OBJC_TYPE(RTCSessionDescription) * answer, 356 NSError * error) { 357 XCTAssertNil(error); 358 XCTAssertNotNil(answer); 359 [weakPC2 360 setLocalDescription:answer 361 completionHandler:^(NSError *error) { 362 XCTAssertNil(error); 363 [weakPC1 364 setRemoteDescription:answer 365 completionHandler:^(NSError *error) { 366 XCTAssertNil(error); 367 dispatch_semaphore_signal(negotiatedSem); 368 }]; 369 }]; 370 }]; 371 }]; 372 }]; 373 }]; 374 375 return 0 == 376 dispatch_semaphore_wait(negotiatedSem, 377 dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC))); 378} 379 380@end 381