xref: /aosp_15_r20/external/webrtc/sdk/objc/unittests/RTCPeerConnectionFactory_xctest.m (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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