blob: ea0b834039e4cb372d0d715fee4d72027dc97d29 [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 "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_extra_data.h"
#include "content/renderer/media/media_stream_impl.h"
#include "content/renderer/media/mock_media_stream_dependency_factory.h"
#include "content/renderer/media/mock_media_stream_dispatcher.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
namespace content {
class MediaStreamImplUnderTest : public MediaStreamImpl {
public:
enum RequestState {
REQUEST_NOT_STARTED,
REQUEST_NOT_COMPLETE,
REQUEST_SUCCEEDED,
REQUEST_FAILED,
};
MediaStreamImplUnderTest(MediaStreamDispatcher* media_stream_dispatcher,
MediaStreamDependencyFactory* dependency_factory)
: MediaStreamImpl(NULL, media_stream_dispatcher, dependency_factory),
state_(REQUEST_NOT_STARTED) {
}
void RequestUserMedia() {
WebKit::WebUserMediaRequest user_media_request;
state_ = REQUEST_NOT_COMPLETE;
requestUserMedia(user_media_request);
}
virtual void CompleteGetUserMediaRequest(
const WebKit::WebMediaStream& stream,
WebKit::WebUserMediaRequest* request_info,
bool request_succeeded) OVERRIDE {
last_generated_stream_ = stream;
state_ = request_succeeded ? REQUEST_SUCCEEDED : REQUEST_FAILED;
}
virtual WebKit::WebMediaStream GetMediaStream(
const GURL& url) OVERRIDE {
return last_generated_stream_;
}
using MediaStreamImpl::OnLocalMediaStreamStop;
const WebKit::WebMediaStream& last_generated_stream() {
return last_generated_stream_;
}
RequestState request_state() const { return state_; }
private:
WebKit::WebMediaStream last_generated_stream_;
RequestState state_;
};
class MediaStreamImplTest : public ::testing::Test {
public:
virtual void SetUp() {
// Create our test object.
ms_dispatcher_.reset(new MockMediaStreamDispatcher());
dependency_factory_.reset(new MockMediaStreamDependencyFactory());
ms_impl_.reset(new MediaStreamImplUnderTest(ms_dispatcher_.get(),
dependency_factory_.get()));
}
WebKit::WebMediaStream RequestLocalMediaStream() {
ms_impl_->RequestUserMedia();
FakeMediaStreamDispatcherComplete();
ChangeVideoSourceStateToLive();
ChangeAudioSourceStateToLive();
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED,
ms_impl_->request_state());
WebKit::WebMediaStream desc = ms_impl_->last_generated_stream();
content::MediaStreamExtraData* extra_data =
static_cast<content::MediaStreamExtraData*>(desc.extraData());
if (!extra_data || !extra_data->stream().get()) {
ADD_FAILURE();
return desc;
}
EXPECT_EQ(1u, extra_data->stream()->GetAudioTracks().size());
EXPECT_EQ(1u, extra_data->stream()->GetVideoTracks().size());
EXPECT_NE(extra_data->stream()->GetAudioTracks()[0]->id(),
extra_data->stream()->GetVideoTracks()[0]->id());
return desc;
}
void FakeMediaStreamDispatcherComplete() {
ms_impl_->OnStreamGenerated(ms_dispatcher_->request_id(),
ms_dispatcher_->stream_label(),
ms_dispatcher_->audio_array(),
ms_dispatcher_->video_array());
}
void ChangeVideoSourceStateToLive() {
if (dependency_factory_->last_video_source() != NULL) {
dependency_factory_->last_video_source()->SetLive();
}
}
void ChangeAudioSourceStateToLive() {
if (dependency_factory_->last_audio_source() != NULL) {
dependency_factory_->last_audio_source()->SetLive();
}
}
void ChangeVideoSourceStateToEnded() {
if (dependency_factory_->last_video_source() != NULL) {
dependency_factory_->last_video_source()->SetEnded();
}
}
void ChangeAudioSourceStateToEnded() {
if (dependency_factory_->last_audio_source() != NULL) {
dependency_factory_->last_audio_source()->SetEnded();
}
}
protected:
scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_;
scoped_ptr<MediaStreamImplUnderTest> ms_impl_;
scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
};
TEST_F(MediaStreamImplTest, LocalMediaStream) {
// Test a stream with both audio and video.
WebKit::WebMediaStream mixed_desc = RequestLocalMediaStream();
// Test a stream with audio only.
WebKit::WebMediaStream audio_desc = RequestLocalMediaStream();
// Test a stream with video only.
WebKit::WebMediaStream video_desc = RequestLocalMediaStream();
// Stop generated local streams.
ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8());
EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
ms_impl_->OnLocalMediaStreamStop(audio_desc.id().utf8());
EXPECT_EQ(2, ms_dispatcher_->stop_stream_counter());
// Test that the MediaStreams are deleted if the owning WebFrame is deleted.
// In the unit test the owning frame is NULL.
ms_impl_->FrameWillClose(NULL);
EXPECT_EQ(3, ms_dispatcher_->stop_stream_counter());
}
// This test what happens if a source to a MediaSteam fails to start.
TEST_F(MediaStreamImplTest, MediaSourceFailToStart) {
ms_impl_->RequestUserMedia();
FakeMediaStreamDispatcherComplete();
ChangeVideoSourceStateToEnded();
ChangeAudioSourceStateToEnded();
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
ms_impl_->request_state());
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
}
// This test what happens if MediaStreamImpl is deleted while the sources of a
// MediaStream is being started.
TEST_F(MediaStreamImplTest, MediaStreamImplShutDown) {
ms_impl_->RequestUserMedia();
FakeMediaStreamDispatcherComplete();
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
ms_impl_->request_state());
ms_impl_.reset();
ChangeAudioSourceStateToLive();
ChangeVideoSourceStateToLive();
}
// This test what happens if the WebFrame is closed while the MediaStream is
// being generated by the MediaStreamDispatcher.
TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) {
ms_impl_->RequestUserMedia();
ms_impl_->FrameWillClose(NULL);
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter());
ChangeAudioSourceStateToLive();
ChangeVideoSourceStateToLive();
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
ms_impl_->request_state());
}
// This test what happens if the WebFrame is closed while the sources are being
// started by MediaStreamDependencyFactory.
TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) {
ms_impl_->RequestUserMedia();
FakeMediaStreamDispatcherComplete();
EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter());
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
ms_impl_->FrameWillClose(NULL);
EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
ChangeAudioSourceStateToLive();
ChangeVideoSourceStateToLive();
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
ms_impl_->request_state());
}
// This test what happens if stop is called on a stream after the frame has
// been reloaded.
TEST_F(MediaStreamImplTest, StopStreamAfterReload) {
WebKit::WebMediaStream mixed_desc = RequestLocalMediaStream();
EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter());
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
ms_impl_->FrameWillClose(NULL);
EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8());
EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
}
} // namespace content