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