blob: ea3dae4ed6d356c8fa0bc582de92f76cfe09e593 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "content/renderer/media/media_stream_extra_data.h"
#include "content/renderer/media/mock_media_stream_dependency_factory.h"
#include "content/renderer/media/mock_web_peer_connection_00_handler_client.h"
#include "content/renderer/media/mock_peer_connection_impl.h"
#include "content/renderer/media/peer_connection_handler_jsep.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebICECandidateDescriptor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebICEOptions.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaHints.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSessionDescriptionDescriptor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
class PeerConnectionHandlerJsepUnderTest : public PeerConnectionHandlerJsep {
public:
PeerConnectionHandlerJsepUnderTest(
WebKit::WebPeerConnection00HandlerClient* client,
MediaStreamDependencyFactory* dependency_factory)
: PeerConnectionHandlerJsep(client, dependency_factory) {
}
webrtc::MockPeerConnectionImpl* native_peer_connection() {
return static_cast<webrtc::MockPeerConnectionImpl*>(
native_peer_connection_.get());
}
};
class PeerConnectionHandlerJsepTest : public ::testing::Test {
public:
PeerConnectionHandlerJsepTest() : mock_peer_connection_(NULL) {
}
void SetUp() {
mock_client_.reset(new WebKit::MockWebPeerConnection00HandlerClient());
mock_dependency_factory_.reset(
new MockMediaStreamDependencyFactory(NULL));
mock_dependency_factory_->CreatePeerConnectionFactory(NULL,
NULL,
NULL,
NULL,
NULL);
pc_handler_.reset(
new PeerConnectionHandlerJsepUnderTest(mock_client_.get(),
mock_dependency_factory_.get()));
WebKit::WebString server_config(
WebKit::WebString::fromUTF8("STUN stun.l.google.com:19302"));
WebKit::WebString username;
pc_handler_->initialize(server_config, username);
mock_peer_connection_ = pc_handler_->native_peer_connection();
ASSERT_TRUE(mock_peer_connection_);
}
// Creates a WebKit local MediaStream.
WebKit::WebMediaStreamDescriptor CreateLocalMediaStream(
const std::string& stream_label) {
std::string video_track_label("video-label");
std::string audio_track_label("audio-label");
talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> native_stream(
mock_dependency_factory_->CreateLocalMediaStream(stream_label));
talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
mock_dependency_factory_->CreateLocalAudioTrack(audio_track_label,
NULL));
native_stream->AddTrack(audio_track);
talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
mock_dependency_factory_->CreateLocalVideoTrack(video_track_label, 0));
native_stream->AddTrack(video_track);
WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources(
static_cast<size_t>(1));
audio_sources[0].initialize(WebKit::WebString::fromUTF8(video_track_label),
WebKit::WebMediaStreamSource::TypeAudio,
WebKit::WebString::fromUTF8("audio_track"));
WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources(
static_cast<size_t>(1));
video_sources[0].initialize(WebKit::WebString::fromUTF8(video_track_label),
WebKit::WebMediaStreamSource::TypeVideo,
WebKit::WebString::fromUTF8("video_track"));
WebKit::WebMediaStreamDescriptor local_stream;
local_stream.initialize(UTF8ToUTF16(stream_label), audio_sources,
video_sources);
local_stream.setExtraData(new MediaStreamExtraData(native_stream));
return local_stream;
}
// Creates a remote MediaStream and adds it to the mocked native
// peer connection.
talk_base::scoped_refptr<webrtc::MediaStreamInterface>
AddRemoteMockMediaStream(const std::string& stream_label,
const std::string& video_track_label,
const std::string& audio_track_label) {
// We use a local stream as a remote since for testing purposes we really
// only need the MediaStreamInterface.
talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> stream(
mock_dependency_factory_->CreateLocalMediaStream(stream_label));
if (!video_track_label.empty()) {
talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
mock_dependency_factory_->CreateLocalVideoTrack(video_track_label,
0));
stream->AddTrack(video_track);
}
if (!audio_track_label.empty()) {
talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
mock_dependency_factory_->CreateLocalAudioTrack(audio_track_label,
NULL));
stream->AddTrack(audio_track);
}
mock_peer_connection_->AddRemoteStream(stream);
return stream;
}
scoped_ptr<WebKit::MockWebPeerConnection00HandlerClient> mock_client_;
scoped_ptr<MockMediaStreamDependencyFactory> mock_dependency_factory_;
scoped_ptr<PeerConnectionHandlerJsepUnderTest> pc_handler_;
// Weak reference to the mocked native peer connection implementation.
webrtc::MockPeerConnectionImpl* mock_peer_connection_;
};
TEST_F(PeerConnectionHandlerJsepTest, Basic) {
// Create offer.
WebKit::WebMediaHints hints;
hints.initialize(true, true);
WebKit::WebSessionDescriptionDescriptor offer =
pc_handler_->createOffer(hints);
EXPECT_FALSE(offer.isNull());
EXPECT_EQ(std::string(mock_peer_connection_->kDummyOffer),
UTF16ToUTF8(offer.initialSDP()));
EXPECT_EQ(hints.audio(), mock_peer_connection_->hint_audio());
EXPECT_EQ(hints.video(), mock_peer_connection_->hint_video());
// Create answer.
WebKit::WebString offer_string = "offer";
hints.reset();
hints.initialize(false, false);
WebKit::WebSessionDescriptionDescriptor answer =
pc_handler_->createAnswer(offer_string, hints);
EXPECT_FALSE(answer.isNull());
EXPECT_EQ(UTF16ToUTF8(offer_string), UTF16ToUTF8(answer.initialSDP()));
EXPECT_EQ(UTF16ToUTF8(offer_string),
mock_peer_connection_->description_sdp());
EXPECT_EQ(hints.audio(), mock_peer_connection_->hint_audio());
EXPECT_EQ(hints.video(), mock_peer_connection_->hint_video());
// Set local description.
PeerConnectionHandlerJsep::Action action =
PeerConnectionHandlerJsep::ActionSDPOffer;
WebKit::WebSessionDescriptionDescriptor description;
WebKit::WebString sdp = "test sdp";
description.initialize(sdp);
EXPECT_TRUE(pc_handler_->setLocalDescription(action, description));
EXPECT_EQ(webrtc::PeerConnectionInterface::kOffer,
mock_peer_connection_->action());
EXPECT_EQ(UTF16ToUTF8(sdp), mock_peer_connection_->description_sdp());
// Get local description.
description.reset();
description = pc_handler_->localDescription();
EXPECT_FALSE(description.isNull());
EXPECT_EQ(UTF16ToUTF8(sdp), UTF16ToUTF8(description.initialSDP()));
// Set remote description.
sdp = "test sdp 2";
description.reset();
description.initialize(sdp);
// PrAnswer
action = PeerConnectionHandlerJsep::ActionSDPPRanswer;
EXPECT_TRUE(pc_handler_->setRemoteDescription(action, description));
EXPECT_EQ(webrtc::PeerConnectionInterface::kPrAnswer,
mock_peer_connection_->action());
EXPECT_EQ(UTF16ToUTF8(sdp), mock_peer_connection_->description_sdp());
// Get remote description.
description.reset();
description = pc_handler_->remoteDescription();
EXPECT_FALSE(description.isNull());
EXPECT_EQ(UTF16ToUTF8(sdp), UTF16ToUTF8(description.initialSDP()));
// Answer
action = PeerConnectionHandlerJsep::ActionSDPAnswer;
EXPECT_TRUE(pc_handler_->setRemoteDescription(action, description));
EXPECT_EQ(webrtc::PeerConnectionInterface::kAnswer,
mock_peer_connection_->action());
EXPECT_EQ(UTF16ToUTF8(sdp), mock_peer_connection_->description_sdp());
// Get remote description.
description.reset();
description = pc_handler_->remoteDescription();
EXPECT_FALSE(description.isNull());
EXPECT_EQ(UTF16ToUTF8(sdp), UTF16ToUTF8(description.initialSDP()));
// Start ICE.
WebKit::WebICEOptions options;
options.initialize(WebKit::WebICEOptions::CandidateTypeAll);
EXPECT_TRUE(pc_handler_->startIce(options));
EXPECT_EQ(webrtc::PeerConnectionInterface::kUseAll,
mock_peer_connection_->ice_options());
// Process ICE message.
WebKit::WebICECandidateDescriptor candidate;
WebKit::WebString label = "0";
sdp = "test sdp";
candidate.initialize(label, sdp);
EXPECT_TRUE(pc_handler_->processIceMessage(candidate));
EXPECT_EQ(0, mock_peer_connection_->sdp_mline_index());
EXPECT_TRUE(mock_peer_connection_->sdp_mid().empty());
EXPECT_EQ(UTF16ToUTF8(sdp), mock_peer_connection_->ice_sdp());
// Add stream.
std::string stream_label = "local_stream";
WebKit::WebMediaStreamDescriptor local_stream(
CreateLocalMediaStream(stream_label));
pc_handler_->addStream(local_stream);
EXPECT_EQ(stream_label, mock_peer_connection_->stream_label());
EXPECT_TRUE(mock_peer_connection_->stream_changes_committed());
// On add stream. ( Remote stream received)
std::string remote_stream_label("remote_stream");
talk_base::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
pc_handler_->OnAddStream(remote_stream);
EXPECT_EQ(remote_stream_label, mock_client_->stream_label());
// Remove stream.
WebKit::WebVector<WebKit::WebMediaStreamDescriptor> empty_streams(
static_cast<size_t>(0));
pc_handler_->removeStream(local_stream);
EXPECT_EQ("", mock_peer_connection_->stream_label());
mock_peer_connection_->ClearStreamChangesCommitted();
EXPECT_TRUE(!mock_peer_connection_->stream_changes_committed());
// On remove stream.
pc_handler_->OnRemoveStream(remote_stream);
EXPECT_TRUE(mock_client_->stream_label().empty());
// Add stream again.
pc_handler_->addStream(local_stream);
EXPECT_EQ(stream_label, mock_peer_connection_->stream_label());
EXPECT_TRUE(mock_peer_connection_->stream_changes_committed());
// On state change.
mock_peer_connection_->SetReadyState(
webrtc::PeerConnectionInterface::kActive);
webrtc::PeerConnectionObserver::StateType state =
webrtc::PeerConnectionObserver::kReadyState;
pc_handler_->OnStateChange(state);
EXPECT_EQ(WebKit::WebPeerConnection00HandlerClient::ReadyStateActive,
mock_client_->ready_state());
// On ICE candidate.
std::string candidate_label = "0";
std::string candidate_sdp = "test sdp";
int sdp_mline_index = 0;
scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
mock_dependency_factory_->CreateIceCandidate(candidate_label,
sdp_mline_index,
candidate_sdp));
pc_handler_->OnIceCandidate(native_candidate.get());
EXPECT_EQ(candidate_label, mock_client_->candidate_label());
EXPECT_EQ(candidate_sdp, mock_client_->candidate_sdp());
EXPECT_TRUE(mock_client_->more_to_follow());
// On ICE complete.
pc_handler_->OnIceComplete();
EXPECT_TRUE(mock_client_->candidate_label().empty());
EXPECT_TRUE(mock_client_->candidate_sdp().empty());
EXPECT_FALSE(mock_client_->more_to_follow());
// Stop.
pc_handler_->stop();
EXPECT_FALSE(pc_handler_->native_peer_connection());
// PC handler is expected to be deleted when stop calls
// MediaStreamImpl::ClosePeerConnection. We own and delete it here instead of
// in the mock.
pc_handler_.reset();
}
// Test that the glue code can receive multiple media streams and can set a
// video renderer on each media stream.
TEST_F(PeerConnectionHandlerJsepTest, ReceiveMultipleRemoteStreams) {
std::string stream_label_1 = "remote_stream_1";
std::string video_track_label_1 = "remote_video_track_1";
std::string audio_track_label_1 = "remote_audio_track_1";
talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream_1(
AddRemoteMockMediaStream(stream_label_1, video_track_label_1,
audio_track_label_1));
std::string stream_label_2 = "remote_stream_2";
std::string video_track_label_2 = "remote_video_track_2";
std::string audio_track_label_2 = "remote_audio_track_2";
talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream_2(
AddRemoteMockMediaStream(stream_label_2, video_track_label_2,
audio_track_label_2));
pc_handler_->OnAddStream(stream_1);
EXPECT_EQ(stream_label_1, mock_client_->stream_label());
pc_handler_->OnAddStream(stream_2);
EXPECT_EQ(stream_label_2, mock_client_->stream_label());
}