Index: talk/app/webrtc/objctests/RTCPeerConnectionTest.mm |
diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm |
deleted file mode 100644 |
index f447ae9ba83c9c73c63d0bbbd7c5bb8c00ec6da9..0000000000000000000000000000000000000000 |
--- a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm |
+++ /dev/null |
@@ -1,350 +0,0 @@ |
-/* |
- * libjingle |
- * Copyright 2013 Google Inc. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions are met: |
- * |
- * 1. Redistributions of source code must retain the above copyright notice, |
- * this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright notice, |
- * this list of conditions and the following disclaimer in the documentation |
- * and/or other materials provided with the distribution. |
- * 3. The name of the author may not be used to endorse or promote products |
- * derived from this software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#import <Foundation/Foundation.h> |
- |
-#import "RTCICEServer.h" |
-#import "RTCMediaConstraints.h" |
-#import "RTCMediaStream.h" |
-#import "RTCPair.h" |
-#import "RTCPeerConnection.h" |
-#import "RTCPeerConnectionFactory.h" |
-#import "RTCPeerConnectionSyncObserver.h" |
-#import "RTCSessionDescription.h" |
-#import "RTCSessionDescriptionSyncObserver.h" |
-#import "RTCVideoRenderer.h" |
-#import "RTCVideoTrack.h" |
- |
-#include "webrtc/base/gunit.h" |
-#include "webrtc/base/ssladapter.h" |
- |
-#if !defined(__has_feature) || !__has_feature(objc_arc) |
-#error "This file requires ARC support." |
-#endif |
- |
-const NSTimeInterval kRTCPeerConnectionTestTimeout = 20; |
- |
-@interface RTCFakeRenderer : NSObject <RTCVideoRenderer> |
-@end |
- |
-@implementation RTCFakeRenderer |
- |
-- (void)setSize:(CGSize)size {} |
-- (void)renderFrame:(RTCI420Frame*)frame {} |
- |
-@end |
- |
-@interface RTCPeerConnectionTest : NSObject |
- |
-// Returns whether the two sessions are of the same type. |
-+ (BOOL)isSession:(RTCSessionDescription*)session1 |
- ofSameTypeAsSession:(RTCSessionDescription*)session2; |
- |
-// Create and add tracks to pc, with the given source, label, and IDs |
-- (RTCMediaStream*)addTracksToPeerConnection:(RTCPeerConnection*)pc |
- withFactory:(RTCPeerConnectionFactory*)factory |
- videoSource:(RTCVideoSource*)videoSource |
- streamLabel:(NSString*)streamLabel |
- videoTrackID:(NSString*)videoTrackID |
- audioTrackID:(NSString*)audioTrackID; |
- |
-- (void)testCompleteSessionWithFactory:(RTCPeerConnectionFactory*)factory; |
- |
-@end |
- |
-@implementation RTCPeerConnectionTest |
- |
-+ (BOOL)isSession:(RTCSessionDescription*)session1 |
- ofSameTypeAsSession:(RTCSessionDescription*)session2 { |
- return [session1.type isEqual:session2.type]; |
-} |
- |
-- (RTCMediaStream*)addTracksToPeerConnection:(RTCPeerConnection*)pc |
- withFactory:(RTCPeerConnectionFactory*)factory |
- videoSource:(RTCVideoSource*)videoSource |
- streamLabel:(NSString*)streamLabel |
- videoTrackID:(NSString*)videoTrackID |
- audioTrackID:(NSString*)audioTrackID { |
- RTCMediaStream* localMediaStream = [factory mediaStreamWithLabel:streamLabel]; |
- // TODO(zeke): Fix this test to create a fake video capturer so that a track |
- // can be created. |
- if (videoSource) { |
- RTCVideoTrack* videoTrack = |
- [factory videoTrackWithID:videoTrackID source:videoSource]; |
- RTCFakeRenderer* videoRenderer = [[RTCFakeRenderer alloc] init]; |
- [videoTrack addRenderer:videoRenderer]; |
- [localMediaStream addVideoTrack:videoTrack]; |
- // Test that removal/re-add works. |
- [localMediaStream removeVideoTrack:videoTrack]; |
- [localMediaStream addVideoTrack:videoTrack]; |
- } |
- RTCAudioTrack* audioTrack = [factory audioTrackWithID:audioTrackID]; |
- [localMediaStream addAudioTrack:audioTrack]; |
- [pc addStream:localMediaStream]; |
- return localMediaStream; |
-} |
- |
-- (void)testCompleteSessionWithFactory:(RTCPeerConnectionFactory*)factory { |
- NSArray* mandatory = @[ |
- [[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"], |
- [[RTCPair alloc] initWithKey:@"internalSctpDataChannels" value:@"true"], |
- ]; |
- RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] init]; |
- RTCMediaConstraints* pcConstraints = |
- [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatory |
- optionalConstraints:nil]; |
- |
- RTCPeerConnectionSyncObserver* offeringExpectations = |
- [[RTCPeerConnectionSyncObserver alloc] init]; |
- RTCPeerConnection* pcOffer = |
- [factory peerConnectionWithICEServers:nil |
- constraints:pcConstraints |
- delegate:offeringExpectations]; |
- |
- RTCPeerConnectionSyncObserver* answeringExpectations = |
- [[RTCPeerConnectionSyncObserver alloc] init]; |
- |
- RTCPeerConnection* pcAnswer = |
- [factory peerConnectionWithICEServers:nil |
- constraints:pcConstraints |
- delegate:answeringExpectations]; |
- // TODO(hughv): Create video capturer |
- RTCVideoCapturer* capturer = nil; |
- RTCVideoSource* videoSource = |
- [factory videoSourceWithCapturer:capturer constraints:constraints]; |
- |
- // Here and below, "oLMS" refers to offerer's local media stream, and "aLMS" |
- // refers to the answerer's local media stream, with suffixes of "a0" and "v0" |
- // for audio and video tracks, resp. These mirror chrome historical naming. |
- RTCMediaStream* oLMSUnused = [self addTracksToPeerConnection:pcOffer |
- withFactory:factory |
- videoSource:videoSource |
- streamLabel:@"oLMS" |
- videoTrackID:@"oLMSv0" |
- audioTrackID:@"oLMSa0"]; |
- |
- RTCDataChannel* offerDC = |
- [pcOffer createDataChannelWithLabel:@"offerDC" |
- config:[[RTCDataChannelInit alloc] init]]; |
- EXPECT_TRUE([offerDC.label isEqual:@"offerDC"]); |
- offerDC.delegate = offeringExpectations; |
- offeringExpectations.dataChannel = offerDC; |
- |
- RTCSessionDescriptionSyncObserver* sdpObserver = |
- [[RTCSessionDescriptionSyncObserver alloc] init]; |
- [pcOffer createOfferWithDelegate:sdpObserver constraints:constraints]; |
- [sdpObserver wait]; |
- EXPECT_TRUE(sdpObserver.success); |
- RTCSessionDescription* offerSDP = sdpObserver.sessionDescription; |
- EXPECT_EQ([@"offer" compare:offerSDP.type options:NSCaseInsensitiveSearch], |
- NSOrderedSame); |
- EXPECT_GT([offerSDP.description length], 0); |
- |
- sdpObserver = [[RTCSessionDescriptionSyncObserver alloc] init]; |
- [answeringExpectations expectSignalingChange:RTCSignalingHaveRemoteOffer]; |
- [answeringExpectations expectAddStream:@"oLMS"]; |
- [pcAnswer setRemoteDescriptionWithDelegate:sdpObserver |
- sessionDescription:offerSDP]; |
- [sdpObserver wait]; |
- |
- RTCMediaStream* aLMSUnused = [self addTracksToPeerConnection:pcAnswer |
- withFactory:factory |
- videoSource:videoSource |
- streamLabel:@"aLMS" |
- videoTrackID:@"aLMSv0" |
- audioTrackID:@"aLMSa0"]; |
- |
- sdpObserver = [[RTCSessionDescriptionSyncObserver alloc] init]; |
- [pcAnswer createAnswerWithDelegate:sdpObserver constraints:constraints]; |
- [sdpObserver wait]; |
- EXPECT_TRUE(sdpObserver.success); |
- RTCSessionDescription* answerSDP = sdpObserver.sessionDescription; |
- EXPECT_EQ([@"answer" compare:answerSDP.type options:NSCaseInsensitiveSearch], |
- NSOrderedSame); |
- EXPECT_GT([answerSDP.description length], 0); |
- |
- [offeringExpectations expectICECandidates:2]; |
- // It's possible to only have 1 ICE candidate for the answerer, since we use |
- // BUNDLE and rtcp-mux by default, and don't provide any ICE servers in this |
- // test. |
- [answeringExpectations expectICECandidates:1]; |
- |
- sdpObserver = [[RTCSessionDescriptionSyncObserver alloc] init]; |
- [answeringExpectations expectSignalingChange:RTCSignalingStable]; |
- [pcAnswer setLocalDescriptionWithDelegate:sdpObserver |
- sessionDescription:answerSDP]; |
- [sdpObserver wait]; |
- EXPECT_TRUE(sdpObserver.sessionDescription == NULL); |
- |
- sdpObserver = [[RTCSessionDescriptionSyncObserver alloc] init]; |
- [offeringExpectations expectSignalingChange:RTCSignalingHaveLocalOffer]; |
- [pcOffer setLocalDescriptionWithDelegate:sdpObserver |
- sessionDescription:offerSDP]; |
- [sdpObserver wait]; |
- EXPECT_TRUE(sdpObserver.sessionDescription == NULL); |
- |
- [offeringExpectations expectICEConnectionChange:RTCICEConnectionChecking]; |
- [offeringExpectations expectICEConnectionChange:RTCICEConnectionConnected]; |
- // TODO(fischman): figure out why this is flaky and re-introduce (and remove |
- // special-casing from the observer!). |
- // [offeringExpectations expectICEConnectionChange:RTCICEConnectionCompleted]; |
- [answeringExpectations expectICEConnectionChange:RTCICEConnectionChecking]; |
- [answeringExpectations expectICEConnectionChange:RTCICEConnectionConnected]; |
- |
- [offeringExpectations expectStateChange:kRTCDataChannelStateOpen]; |
- [answeringExpectations expectDataChannel:@"offerDC"]; |
- [answeringExpectations expectStateChange:kRTCDataChannelStateOpen]; |
- |
- [offeringExpectations expectICEGatheringChange:RTCICEGatheringComplete]; |
- [answeringExpectations expectICEGatheringChange:RTCICEGatheringComplete]; |
- |
- sdpObserver = [[RTCSessionDescriptionSyncObserver alloc] init]; |
- [offeringExpectations expectSignalingChange:RTCSignalingStable]; |
- [offeringExpectations expectAddStream:@"aLMS"]; |
- [pcOffer setRemoteDescriptionWithDelegate:sdpObserver |
- sessionDescription:answerSDP]; |
- [sdpObserver wait]; |
- EXPECT_TRUE(sdpObserver.sessionDescription == NULL); |
- |
- EXPECT_TRUE([offerSDP.type isEqual:pcOffer.localDescription.type]); |
- EXPECT_TRUE([answerSDP.type isEqual:pcOffer.remoteDescription.type]); |
- EXPECT_TRUE([offerSDP.type isEqual:pcAnswer.remoteDescription.type]); |
- EXPECT_TRUE([answerSDP.type isEqual:pcAnswer.localDescription.type]); |
- |
- for (RTCICECandidate* candidate in offeringExpectations |
- .releaseReceivedICECandidates) { |
- [pcAnswer addICECandidate:candidate]; |
- } |
- for (RTCICECandidate* candidate in answeringExpectations |
- .releaseReceivedICECandidates) { |
- [pcOffer addICECandidate:candidate]; |
- } |
- |
- EXPECT_TRUE( |
- [offeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- EXPECT_TRUE( |
- [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- |
- EXPECT_EQ(pcOffer.signalingState, RTCSignalingStable); |
- EXPECT_EQ(pcAnswer.signalingState, RTCSignalingStable); |
- |
- // Test send and receive UTF-8 text |
- NSString* text = @"你好"; |
- NSData* textData = [text dataUsingEncoding:NSUTF8StringEncoding]; |
- RTCDataBuffer* buffer = |
- [[RTCDataBuffer alloc] initWithData:textData isBinary:NO]; |
- [answeringExpectations expectMessage:[textData copy] isBinary:NO]; |
- EXPECT_TRUE([offeringExpectations.dataChannel sendData:buffer]); |
- EXPECT_TRUE( |
- [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- |
- // Test send and receive binary data |
- const size_t byteLength = 5; |
- char bytes[byteLength] = {1, 2, 3, 4, 5}; |
- NSData* byteData = [NSData dataWithBytes:bytes length:byteLength]; |
- buffer = [[RTCDataBuffer alloc] initWithData:byteData isBinary:YES]; |
- [answeringExpectations expectMessage:[byteData copy] isBinary:YES]; |
- EXPECT_TRUE([offeringExpectations.dataChannel sendData:buffer]); |
- EXPECT_TRUE( |
- [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- |
- [offeringExpectations expectStateChange:kRTCDataChannelStateClosing]; |
- [answeringExpectations expectStateChange:kRTCDataChannelStateClosing]; |
- [offeringExpectations expectStateChange:kRTCDataChannelStateClosed]; |
- [answeringExpectations expectStateChange:kRTCDataChannelStateClosed]; |
- |
- [answeringExpectations.dataChannel close]; |
- [offeringExpectations.dataChannel close]; |
- |
- EXPECT_TRUE( |
- [offeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- EXPECT_TRUE( |
- [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- // Don't need to listen to further state changes. |
- // TODO(tkchin): figure out why Closed->Closing without this. |
- offeringExpectations.dataChannel.delegate = nil; |
- answeringExpectations.dataChannel.delegate = nil; |
- |
- // Let the audio feedback run for 2s to allow human testing and to ensure |
- // things stabilize. TODO(fischman): replace seconds with # of video frames, |
- // when we have video flowing. |
- [[NSRunLoop currentRunLoop] |
- runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; |
- |
- [offeringExpectations expectICEConnectionChange:RTCICEConnectionClosed]; |
- [answeringExpectations expectICEConnectionChange:RTCICEConnectionClosed]; |
- [offeringExpectations expectSignalingChange:RTCSignalingClosed]; |
- [answeringExpectations expectSignalingChange:RTCSignalingClosed]; |
- |
- [pcOffer close]; |
- [pcAnswer close]; |
- |
- EXPECT_TRUE( |
- [offeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- EXPECT_TRUE( |
- [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: |
- kRTCPeerConnectionTestTimeout]); |
- |
- capturer = nil; |
- videoSource = nil; |
- pcOffer = nil; |
- pcAnswer = nil; |
- // TODO(fischman): be stricter about shutdown checks; ensure thread |
- // counts return to where they were before the test kicked off, and |
- // that all objects have in fact shut down. |
-} |
- |
-@end |
- |
-// TODO(fischman): move {Initialize,Cleanup}SSL into alloc/dealloc of |
-// RTCPeerConnectionTest and avoid the appearance of RTCPeerConnectionTest being |
-// a TestBase since it's not. |
-TEST(RTCPeerConnectionTest, SessionTest) { |
- @autoreleasepool { |
- rtc::InitializeSSL(); |
- // Since |factory| will own the signaling & worker threads, it's important |
- // that it outlive the created PeerConnections since they self-delete on the |
- // signaling thread, and if |factory| is freed first then a last refcount on |
- // the factory will expire during this teardown, causing the signaling |
- // thread to try to Join() with itself. This is a hack to ensure that the |
- // factory outlives RTCPeerConnection:dealloc. |
- // See https://code.google.com/p/webrtc/issues/detail?id=3100. |
- RTCPeerConnectionFactory* factory = [[RTCPeerConnectionFactory alloc] init]; |
- @autoreleasepool { |
- RTCPeerConnectionTest* pcTest = [[RTCPeerConnectionTest alloc] init]; |
- [pcTest testCompleteSessionWithFactory:factory]; |
- } |
- rtc::CleanupSSL(); |
- } |
-} |