summaryrefslogtreecommitdiffstats
path: root/webkit/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-29 21:59:16 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-29 21:59:16 +0000
commit9830942170ffdfa01625dc1b34fcc3138e873071 (patch)
treed3077810b2f5b79466824009aadbfd01703270ac /webkit/media
parent84f4dc00fe3211465900921ab044cc95606c8f85 (diff)
downloadchromium_src-9830942170ffdfa01625dc1b34fcc3138e873071.zip
chromium_src-9830942170ffdfa01625dc1b34fcc3138e873071.tar.gz
chromium_src-9830942170ffdfa01625dc1b34fcc3138e873071.tar.bz2
Rewrite BufferedDataSource tests to use real BufferedResourceLoader objects.
The new tests expose the very real memory leak described in bug 100914. The fix for the leak is non trivial and will be addressed in a follow up patch. BUG=100914 Review URL: http://codereview.chromium.org/8649002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112043 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/media')
-rw-r--r--webkit/media/buffered_data_source.h2
-rw-r--r--webkit/media/buffered_data_source_unittest.cc876
-rw-r--r--webkit/media/buffered_resource_loader.h2
-rw-r--r--webkit/media/test_response_generator.cc84
-rw-r--r--webkit/media/test_response_generator.h59
5 files changed, 416 insertions, 607 deletions
diff --git a/webkit/media/buffered_data_source.h b/webkit/media/buffered_data_source.h
index 7987d09..d7dc37f 100644
--- a/webkit/media/buffered_data_source.h
+++ b/webkit/media/buffered_data_source.h
@@ -69,7 +69,7 @@ class BufferedDataSource : public WebDataSource {
int64 first_byte_position, int64 last_byte_position);
private:
- friend class BufferedDataSourceTest2;
+ friend class BufferedDataSourceTest;
// Posted to perform initialization on render thread and start resource
// loading.
diff --git a/webkit/media/buffered_data_source_unittest.cc b/webkit/media/buffered_data_source_unittest.cc
index ce14c7a..2bcae64 100644
--- a/webkit/media/buffered_data_source_unittest.cc
+++ b/webkit/media/buffered_data_source_unittest.cc
@@ -2,41 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <algorithm>
-
#include "base/bind.h"
-#include "base/test/test_timeouts.h"
#include "media/base/media_log.h"
#include "media/base/mock_callback.h"
#include "media/base/mock_filter_host.h"
#include "media/base/mock_filters.h"
-#include "net/base/net_errors.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "webkit/media/buffered_data_source.h"
#include "webkit/mocks/mock_webframeclient.h"
#include "webkit/mocks/mock_weburlloader.h"
+#include "webkit/media/test_response_generator.h"
using ::testing::_;
using ::testing::Assign;
-using ::testing::AtLeast;
-using ::testing::DeleteArg;
-using ::testing::DoAll;
-using ::testing::InSequence;
using ::testing::Invoke;
-using ::testing::InvokeWithoutArgs;
-using ::testing::NotNull;
-using ::testing::Return;
-using ::testing::ReturnRef;
-using ::testing::SetArgumentPointee;
+using ::testing::Mock;
using ::testing::StrictMock;
using ::testing::NiceMock;
-using ::testing::WithArgs;
using WebKit::WebFrame;
-using WebKit::WebString;
-using WebKit::WebURLError;
+using WebKit::WebURLLoader;
using WebKit::WebURLResponse;
using WebKit::WebView;
@@ -45,487 +31,325 @@ using webkit_glue::MockWebURLLoader;
namespace webkit_media {
-static const char* kHttpUrl = "http://test";
-static const char* kFileUrl = "file://test";
-static const int kDataSize = 1024;
-static const int kMaxCacheMissesBeforeFailTest = 20;
-
-enum NetworkState {
- NONE,
- LOADED,
- LOADING
-};
-
-// A mock BufferedDataSource to inject mock BufferedResourceLoader through
-// CreateResourceLoader() method.
+// Overrides CreateResourceLoader() to permit injecting a MockWebURLLoader.
+// Also keeps track of whether said MockWebURLLoader is actively loading.
class MockBufferedDataSource : public BufferedDataSource {
public:
MockBufferedDataSource(MessageLoop* message_loop, WebFrame* frame)
- : BufferedDataSource(message_loop, frame, new media::MediaLog()) {
+ : BufferedDataSource(message_loop, frame, new media::MediaLog()),
+ loading_(false) {
}
- virtual base::TimeDelta GetTimeoutMilliseconds() {
- return base::TimeDelta::FromMilliseconds(
- TestTimeouts::tiny_timeout_ms());
+ MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*(int64, int64));
+ BufferedResourceLoader* CreateMockResourceLoader(int64 first_byte_position,
+ int64 last_byte_position) {
+ CHECK(!loading_) << "Previous resource load wasn't cancelled";
+
+ BufferedResourceLoader* loader =
+ BufferedDataSource::CreateResourceLoader(first_byte_position,
+ last_byte_position);
+
+ // Keep track of active loading state via loadAsynchronously() and cancel().
+ NiceMock<MockWebURLLoader>* url_loader = new NiceMock<MockWebURLLoader>();
+ ON_CALL(*url_loader, loadAsynchronously(_, _))
+ .WillByDefault(Assign(&loading_, true));
+ ON_CALL(*url_loader, cancel())
+ .WillByDefault(Assign(&loading_, false));
+
+ // TODO(scherkus): this is a real leak detected by http://crbug.com/100914
+ // but the fix will have to wait for a more invasive follow up patch.
+ //
+ // If you're curious what the fix is, we no longer need the reference
+ // counting added to BufferedResourceLoader in r23274 since we started
+ // using WebURLLoader in r69429.
+ Mock::AllowLeak(url_loader);
+
+ loader->SetURLLoaderForTest(url_loader);
+ return loader;
}
- MOCK_METHOD2(CreateResourceLoader,
- BufferedResourceLoader*(int64 first_position,
- int64 last_position));
+ bool loading() { return loading_; }
+ void set_loading(bool loading) { loading_ = loading; }
private:
+ // Whether the resource load has starting loading but yet to been cancelled.
+ bool loading_;
+
DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource);
};
-class MockBufferedResourceLoader : public BufferedResourceLoader {
- public:
- MockBufferedResourceLoader()
- : BufferedResourceLoader(GURL(), 0, 0, kThresholdDefer,
- 0, 0, new media::MediaLog()) {
- }
-
- MOCK_METHOD3(Start, void(net::OldCompletionCallback* read_callback,
- const base::Closure& network_callback,
- WebFrame* frame));
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD4(Read, void(int64 position, int read_size, uint8* buffer,
- net::OldCompletionCallback* callback));
- MOCK_METHOD0(content_length, int64());
- MOCK_METHOD0(instance_size, int64());
- MOCK_METHOD0(range_supported, bool());
- MOCK_METHOD0(network_activity, bool());
- MOCK_METHOD0(url, const GURL&());
- MOCK_METHOD0(GetBufferedFirstBytePosition, int64());
- MOCK_METHOD0(GetBufferedLastBytePosition, int64());
-
- protected:
- ~MockBufferedResourceLoader() {}
-
- DISALLOW_COPY_AND_ASSIGN(MockBufferedResourceLoader);
-};
+static const int64 kFileSize = 5000000;
+static const int64 kFarReadPosition = 4000000;
+static const size_t kDataSize = 1024;
class BufferedDataSourceTest : public testing::Test {
public:
BufferedDataSourceTest()
- : view_(WebView::create(NULL)) {
+ : response_generator_(GURL("http://localhost/foo.webm"), kFileSize),
+ view_(WebView::create(NULL)),
+ message_loop_(MessageLoop::current()) {
view_->initializeMainFrame(&client_);
- message_loop_ = MessageLoop::current();
- for (size_t i = 0; i < sizeof(data_); ++i) {
- data_[i] = i;
- }
+ data_source_ = new MockBufferedDataSource(message_loop_,
+ view_->mainFrame());
+ data_source_->set_host(&host_);
}
virtual ~BufferedDataSourceTest() {
view_->close();
}
- void ExpectCreateAndStartResourceLoader(int start_error) {
- EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
- .WillOnce(Return(loader_.get()));
-
- EXPECT_CALL(*loader_, Start(NotNull(), _, NotNull()))
- .WillOnce(
- DoAll(Assign(&error_, start_error),
- Invoke(this,
- &BufferedDataSourceTest::InvokeStartCallback)));
+ void Initialize(media::PipelineStatus expected) {
+ ExpectCreateResourceLoader();
+ data_source_->Initialize(response_generator_.gurl().spec(),
+ media::NewExpectedStatusCB(expected));
+ message_loop_->RunAllPending();
}
- void InitializeDataSource(const char* url, int error,
- bool partial_response, int64 instance_size,
- NetworkState networkState) {
- // Saves the url first.
- gurl_ = GURL(url);
-
- data_source_ = new MockBufferedDataSource(MessageLoop::current(),
- view_->mainFrame());
- data_source_->set_host(&host_);
-
- scoped_refptr<NiceMock<MockBufferedResourceLoader> > first_loader(
- new NiceMock<MockBufferedResourceLoader>());
-
- // Creates the mock loader to be injected.
- loader_ = first_loader;
-
- bool initialized_ok = (error == net::OK);
- bool loaded = networkState == LOADED;
- {
- InSequence s;
- ExpectCreateAndStartResourceLoader(error);
-
- // In the case of an invalid partial response we expect a second loader
- // to be created.
- if (partial_response && (error == net::ERR_INVALID_RESPONSE)) {
- // Verify that the initial loader is stopped.
- EXPECT_CALL(*loader_, url())
- .WillRepeatedly(ReturnRef(gurl_));
- EXPECT_CALL(*loader_, Stop());
+ // Helper to initialize tests with a valid 206 response.
+ void InitializeWith206Response() {
+ Initialize(media::PIPELINE_OK);
- // Replace loader_ with a new instance.
- loader_ = new NiceMock<MockBufferedResourceLoader>();
-
- // Create and start. Make sure Start() is called on the new loader.
- ExpectCreateAndStartResourceLoader(net::OK);
-
- // Update initialization variable since we know the second loader will
- // return OK.
- initialized_ok = true;
- }
- }
-
- // Attach a static function that deletes the memory referred by the
- // "callback" parameter.
- ON_CALL(*loader_, Read(_, _, _ , _))
- .WillByDefault(DeleteArg<3>());
-
- ON_CALL(*loader_, instance_size())
- .WillByDefault(Return(instance_size));
-
- // range_supported() return true if we expect to get a partial response.
- ON_CALL(*loader_, range_supported())
- .WillByDefault(Return(partial_response));
-
- ON_CALL(*loader_, url())
- .WillByDefault(ReturnRef(gurl_));
- media::PipelineStatus expected_init_status = media::PIPELINE_OK;
- if (initialized_ok) {
- // Expected loaded or not.
- EXPECT_CALL(host_, SetLoaded(loaded));
-
- if (instance_size != -1)
- EXPECT_CALL(host_, SetTotalBytes(instance_size));
-
- if (loaded)
- EXPECT_CALL(host_, SetBufferedBytes(instance_size));
- else
- EXPECT_CALL(host_, SetBufferedBytes(0));
-
- if (!partial_response || instance_size == -1)
- EXPECT_CALL(host_, SetStreaming(true));
-
- } else {
- expected_init_status = media::PIPELINE_ERROR_NETWORK;
- EXPECT_CALL(*loader_, Stop());
- }
-
- // Actual initialization of the data source.
- data_source_->Initialize(url,
- media::NewExpectedStatusCB(expected_init_status));
- message_loop_->RunAllPending();
-
- if (initialized_ok) {
- // Verify the size of the data source.
- int64 size;
- if (instance_size != -1 && (loaded || partial_response)) {
- EXPECT_TRUE(data_source_->GetSize(&size));
- EXPECT_EQ(instance_size, size);
- } else {
- EXPECT_TRUE(data_source_->IsStreaming());
- }
- }
+ EXPECT_CALL(host_, SetLoaded(false));
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
+ EXPECT_CALL(host_, SetBufferedBytes(0));
+ Respond(response_generator_.Generate206(0));
}
- void StopDataSource() {
- if (loader_) {
- InSequence s;
- EXPECT_CALL(*loader_, Stop());
+ // Stops any active loaders and shuts down the data source.
+ //
+ // This typically happens when the page is closed and for our purposes is
+ // appropriate to do when tearing down a test.
+ void Stop() {
+ if (data_source_->loading()) {
+ loader()->didFail(url_loader(), response_generator_.GenerateError());
+ message_loop_->RunAllPending();
}
data_source_->Stop(media::NewExpectedClosure());
message_loop_->RunAllPending();
}
- void InvokeStartCallback(
- net::OldCompletionCallback* callback,
- const base::Closure& network_callback,
- WebFrame* frame) {
- callback->RunWithParams(Tuple1<int>(error_));
- delete callback;
- // TODO(hclam): Save network_callback.
+ void ExpectCreateResourceLoader() {
+ EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
+ .WillOnce(Invoke(data_source_.get(),
+ &MockBufferedDataSource::CreateMockResourceLoader));
+ message_loop_->RunAllPending();
}
- void InvokeReadCallback(int64 position, int size, uint8* buffer,
- net::OldCompletionCallback* callback) {
- if (error_ > 0)
- memcpy(buffer, data_ + static_cast<int>(position), error_);
- callback->RunWithParams(Tuple1<int>(error_));
- delete callback;
+ void Respond(const WebURLResponse& response) {
+ loader()->didReceiveResponse(url_loader(), response);
+ message_loop_->RunAllPending();
}
- void ReadDataSourceHit(int64 position, int size, int read_size) {
- EXPECT_TRUE(loader_);
-
- InSequence s;
- // Expect the read is delegated to the resource loader.
- EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
- .WillOnce(DoAll(Assign(&error_, read_size),
- Invoke(this,
- &BufferedDataSourceTest::InvokeReadCallback)));
-
- // The read has succeeded, so read callback will be called.
- EXPECT_CALL(*this, ReadCallback(read_size));
-
- data_source_->Read(
- position, size, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(this)));
+ void FinishRead() {
+ loader()->didReceiveData(url_loader(), data_, kDataSize, kDataSize);
message_loop_->RunAllPending();
+ }
- // Make sure data is correct.
- EXPECT_EQ(0,
- memcmp(buffer_, data_ + static_cast<int>(position), read_size));
+ void FinishLoading() {
+ data_source_->set_loading(false);
+ loader()->didFinishLoading(url_loader(), 0);
+ message_loop_->RunAllPending();
}
- void ReadDataSourceHang(int64 position, int size) {
- EXPECT_TRUE(loader_);
+ MOCK_METHOD1(ReadCallback, void(size_t size));
- // Expect a call to read, but the call never returns.
- EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()));
- data_source_->Read(
- position, size, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(this)));
+ void ReadAt(int64 position) {
+ data_source_->Read(position, kDataSize, buffer_,
+ base::Bind(&BufferedDataSourceTest::ReadCallback,
+ base::Unretained(this)));
message_loop_->RunAllPending();
+ }
- // Now expect the read to return after aborting the data source.
- EXPECT_CALL(*this, ReadCallback(_));
- EXPECT_CALL(*loader_, Stop());
- data_source_->Abort();
- message_loop_->RunAllPending();
+ // Accessors for private variables on |data_source_|.
+ BufferedResourceLoader* loader() { return data_source_->loader_.get(); }
+ WebURLLoader* url_loader() { return loader()->url_loader_.get(); }
- // The loader has now been stopped. Set this to null so that when the
- // DataSource is stopped, it does not expect a call to stop the loader.
- loader_ = NULL;
+ media::Preload preload() { return data_source_->preload_; }
+ BufferedResourceLoader::DeferStrategy defer_strategy() {
+ return loader()->defer_strategy_;
}
+ int data_source_bitrate() { return data_source_->bitrate_; }
+ int data_source_playback_rate() { return data_source_->playback_rate_; }
+ int loader_bitrate() { return loader()->bitrate_; }
+ int loader_playback_rate() { return loader()->playback_rate_; }
- void ReadDataSourceMiss(int64 position, int size, int start_error) {
- EXPECT_TRUE(loader_);
-
- // 1. Reply with a cache miss for the read.
- {
- InSequence s;
- EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
- .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS),
- Invoke(this,
- &BufferedDataSourceTest::InvokeReadCallback)));
- EXPECT_CALL(*loader_, Stop());
- }
- // 2. Then the current loader will be stop and destroyed.
- NiceMock<MockBufferedResourceLoader> *new_loader =
- new NiceMock<MockBufferedResourceLoader>();
- EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
- .WillOnce(Return(new_loader));
-
- // 3. Then the new loader will be started.
- EXPECT_CALL(*new_loader, Start(NotNull(), _, NotNull()))
- .WillOnce(DoAll(Assign(&error_, start_error),
- Invoke(this,
- &BufferedDataSourceTest::InvokeStartCallback)));
-
- if (start_error == net::OK) {
- EXPECT_CALL(*new_loader, range_supported())
- .WillRepeatedly(Return(loader_->range_supported()));
-
- // 4a. Then again a read request is made to the new loader.
- EXPECT_CALL(*new_loader, Read(position, size, NotNull(), NotNull()))
- .WillOnce(DoAll(Assign(&error_, size),
- Invoke(this,
- &BufferedDataSourceTest::InvokeReadCallback)));
-
- EXPECT_CALL(*this, ReadCallback(size));
- } else {
- // 4b. The read callback is called with an error because Start() on the
- // new loader returned an error.
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- }
+ scoped_refptr<MockBufferedDataSource> data_source_;
- data_source_->Read(
- position, size, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(this)));
- message_loop_->RunAllPending();
+ TestResponseGenerator response_generator_;
+ MockWebFrameClient client_;
+ WebView* view_;
- // Make sure data is correct.
- if (start_error == net::OK)
- EXPECT_EQ(0, memcmp(buffer_, data_ + static_cast<int>(position), size));
+ StrictMock<media::MockFilterHost> host_;
+ MessageLoop* message_loop_;
- loader_ = new_loader;
- }
+ private:
+ // Used for calling BufferedDataSource::Read().
+ uint8 buffer_[kDataSize];
- void ReadDataSourceFailed(int64 position, int size, int error) {
- EXPECT_TRUE(loader_);
+ // Used for calling BufferedResourceLoader::didReceiveData().
+ char data_[kDataSize];
- // 1. Expect the read is delegated to the resource loader.
- EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
- .WillOnce(DoAll(Assign(&error_, error),
- Invoke(this,
- &BufferedDataSourceTest::InvokeReadCallback)));
+ DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
+};
- // 2. Host will then receive an error.
- EXPECT_CALL(*loader_, Stop());
+TEST_F(BufferedDataSourceTest, Range_Supported) {
+ Initialize(media::PIPELINE_OK);
- // 3. The read has failed, so read callback will be called.
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ EXPECT_CALL(host_, SetLoaded(false));
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
+ EXPECT_CALL(host_, SetBufferedBytes(0));
+ Respond(response_generator_.Generate206(0));
- data_source_->Read(
- position, size, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(this)));
+ EXPECT_TRUE(data_source_->loading());
+ Stop();
+}
- message_loop_->RunAllPending();
- }
+TEST_F(BufferedDataSourceTest, Range_NotFound) {
+ Initialize(media::PIPELINE_ERROR_NETWORK);
- BufferedResourceLoader* InvokeCacheMissCreateResourceLoader(int64 start,
- int64 end) {
- NiceMock<MockBufferedResourceLoader>* new_loader =
- new NiceMock<MockBufferedResourceLoader>();
+ // It'll try again.
+ //
+ // TODO(scherkus): don't try again on errors http://crbug.com/105230
+ ExpectCreateResourceLoader();
+ Respond(response_generator_.Generate404());
- EXPECT_CALL(*new_loader, Start(NotNull(), _, NotNull()))
- .WillOnce(DoAll(Assign(&error_, net::OK),
- Invoke(this,
- &BufferedDataSourceTest::InvokeStartCallback)));
+ // Now it's done and will fail.
+ Respond(response_generator_.Generate404());
- EXPECT_CALL(*new_loader, range_supported())
- .WillRepeatedly(Return(loader_->range_supported()));
+ EXPECT_FALSE(data_source_->loading());
+ Stop();
+}
- int error = net::ERR_FAILED;
- if (cache_miss_count_ < kMaxCacheMissesBeforeFailTest) {
- cache_miss_count_++;
- error = net::ERR_CACHE_MISS;
- }
+TEST_F(BufferedDataSourceTest, Range_NotSupported) {
+ Initialize(media::PIPELINE_OK);
- EXPECT_CALL(*new_loader, Read(start, _, NotNull(), NotNull()))
- .WillOnce(DoAll(Assign(&error_, error),
- Invoke(this,
- &BufferedDataSourceTest::InvokeReadCallback)));
+ // It'll try again.
+ //
+ // TODO(scherkus): try to reuse existing connection http://crbug.com/105231
+ ExpectCreateResourceLoader();
+ Respond(response_generator_.Generate200());
- loader_ = new_loader;
- return new_loader;
- }
+ // Now it'll succeed.
+ EXPECT_CALL(host_, SetLoaded(false));
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
+ EXPECT_CALL(host_, SetBufferedBytes(0));
+ EXPECT_CALL(host_, SetStreaming(true));
+ Respond(response_generator_.Generate200());
- void ReadDataSourceAlwaysCacheMiss(int64 position, int size) {
- cache_miss_count_ = 0;
+ EXPECT_TRUE(data_source_->loading());
+ Stop();
+}
- EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
- .WillRepeatedly(Invoke(
- this,
- &BufferedDataSourceTest::InvokeCacheMissCreateResourceLoader));
+TEST_F(BufferedDataSourceTest, Range_MissingContentRange) {
+ Initialize(media::PIPELINE_ERROR_NETWORK);
- EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
- .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS),
- Invoke(this,
- &BufferedDataSourceTest::InvokeReadCallback)));
+ // It'll try again.
+ //
+ // TODO(scherkus): don't try again on errors http://crbug.com/105230
+ ExpectCreateResourceLoader();
+ Respond(response_generator_.Generate206(
+ 0, TestResponseGenerator::kNoContentRange));
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ // Now it's done and will fail.
+ Respond(response_generator_.Generate206(
+ 0, TestResponseGenerator::kNoContentRange));
- data_source_->Read(
- position, size, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(this)));
+ EXPECT_FALSE(data_source_->loading());
+ Stop();
+}
- message_loop_->RunAllPending();
+TEST_F(BufferedDataSourceTest, Range_MissingContentLength) {
+ Initialize(media::PIPELINE_OK);
- EXPECT_LT(cache_miss_count_, kMaxCacheMissesBeforeFailTest);
- }
+ // It'll manage without a Content-Length response.
+ EXPECT_CALL(host_, SetLoaded(false));
+ EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
+ EXPECT_CALL(host_, SetBufferedBytes(0));
+ Respond(response_generator_.Generate206(
+ 0, TestResponseGenerator::kNoContentLength));
- MOCK_METHOD1(ReadCallback, void(size_t size));
+ EXPECT_TRUE(data_source_->loading());
+ Stop();
+}
- scoped_refptr<NiceMock<MockBufferedResourceLoader> > loader_;
- scoped_refptr<MockBufferedDataSource> data_source_;
+TEST_F(BufferedDataSourceTest, Range_WrongContentRange) {
+ Initialize(media::PIPELINE_ERROR_NETWORK);
- MockWebFrameClient client_;
- WebView* view_;
+ // It'll try again.
+ //
+ // TODO(scherkus): don't try again on errors http://crbug.com/105230
+ ExpectCreateResourceLoader();
+ Respond(response_generator_.Generate206(1337));
- StrictMock<media::MockFilterHost> host_;
- GURL gurl_;
- MessageLoop* message_loop_;
+ // Now it's done and will fail.
+ Respond(response_generator_.Generate206(1337));
- int error_;
- uint8 buffer_[1024];
- uint8 data_[1024];
+ EXPECT_FALSE(data_source_->loading());
+ Stop();
+}
- int cache_miss_count_;
+// Test the case where the initial response from the server indicates that
+// Range requests are supported, but a later request prove otherwise.
+TEST_F(BufferedDataSourceTest, Range_ServerLied) {
+ InitializeWith206Response();
- private:
- DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
-};
+ // Read causing a new request to be made -- we'll expect it to error.
+ ExpectCreateResourceLoader();
+ ReadAt(kFarReadPosition);
-TEST_F(BufferedDataSourceTest, InitializationSuccess) {
- InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
- StopDataSource();
-}
+ // Return a 200 in response to a range request.
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ Respond(response_generator_.Generate200());
-TEST_F(BufferedDataSourceTest, InitiailizationFailed) {
- InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, false, 0, NONE);
- StopDataSource();
+ EXPECT_FALSE(data_source_->loading());
+ Stop();
}
-TEST_F(BufferedDataSourceTest, MissingContentLength) {
- InitializeDataSource(kHttpUrl, net::OK, true, -1, LOADING);
- StopDataSource();
-}
+TEST_F(BufferedDataSourceTest, Range_AbortWhileReading) {
+ InitializeWith206Response();
-TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) {
- InitializeDataSource(kHttpUrl, net::OK, false, 1024, LOADING);
- StopDataSource();
-}
+ // Make sure there's a pending read -- we'll expect it to error.
+ ReadAt(0);
-// Test the case where we get a 206 response, but no Content-Range header.
-TEST_F(BufferedDataSourceTest, MissingContentRange) {
- InitializeDataSource(kHttpUrl, net::ERR_INVALID_RESPONSE, true, 1024,
- LOADING);
- StopDataSource();
-}
+ // Abort!!!
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ data_source_->Abort();
+ message_loop_->RunAllPending();
-TEST_F(BufferedDataSourceTest,
- MissingContentLengthAndRangeRequestNotSupported) {
- InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING);
- StopDataSource();
+ EXPECT_FALSE(data_source_->loading());
+ Stop();
}
-TEST_F(BufferedDataSourceTest, ReadCacheHit) {
- InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING);
-
- // Performs read with cache hit.
- ReadDataSourceHit(10, 10, 10);
+TEST_F(BufferedDataSourceTest, Range_TooManyRetries) {
+ InitializeWith206Response();
- // Performs read with cache hit but partially filled.
- ReadDataSourceHit(20, 10, 5);
+ // Make sure there's a pending read -- we'll expect it to error.
+ ReadAt(0);
- StopDataSource();
-}
+ // It'll try three times.
+ ExpectCreateResourceLoader();
+ FinishLoading();
+ Respond(response_generator_.Generate206(0));
-TEST_F(BufferedDataSourceTest, ReadCacheMiss) {
- InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
- ReadDataSourceMiss(1000, 10, net::OK);
- ReadDataSourceMiss(20, 10, net::OK);
- StopDataSource();
-}
+ ExpectCreateResourceLoader();
+ FinishLoading();
+ Respond(response_generator_.Generate206(0));
-// Test the case where the initial response from the server indicates that
-// Range requests are supported, but a later request prove otherwise.
-TEST_F(BufferedDataSourceTest, ServerLiesAboutRangeSupport) {
- InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
- ReadDataSourceHit(10, 10, 10);
- ReadDataSourceMiss(1000, 10, net::ERR_INVALID_RESPONSE);
- StopDataSource();
-}
+ ExpectCreateResourceLoader();
+ FinishLoading();
+ Respond(response_generator_.Generate206(0));
-TEST_F(BufferedDataSourceTest, ReadHang) {
- InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING);
- ReadDataSourceHang(10, 10);
- StopDataSource();
-}
+ // It'll error after this.
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ FinishLoading();
-TEST_F(BufferedDataSourceTest, ReadFailed) {
- InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
- ReadDataSourceHit(10, 10, 10);
- ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET);
- StopDataSource();
+ EXPECT_FALSE(data_source_->loading());
+ Stop();
}
-// Helper that sets |*value| to true. Useful for binding into a Closure.
static void SetTrue(bool* value) {
*value = true;
}
@@ -537,199 +361,22 @@ static void SetTrue(bool* value) {
// object runs on the render message loop, Stop() will not complete if it
// requires a task to run on the the message loop that is being blocked.
TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
- InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
+ InitializeWith206Response();
// Stop() the data source, using a callback that lets us verify that it was
// called before Stop() returns. This is to make sure that the callback does
// not require |message_loop_| to execute tasks before being called.
bool stop_done_called = false;
+ EXPECT_TRUE(data_source_->loading());
data_source_->Stop(base::Bind(&SetTrue, &stop_done_called));
// Verify that the callback was called inside the Stop() call.
EXPECT_TRUE(stop_done_called);
-
message_loop_->RunAllPending();
}
-TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) {
- InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
-
- // Setup a way to verify that Read() is not called on the loader.
- // We are doing this to make sure that the ReadTask() is still on
- // the message loop queue when Abort() is called.
- bool read_called = false;
- ON_CALL(*loader_, Read(_, _, _ , _))
- .WillByDefault(DoAll(Assign(&read_called, true),
- DeleteArg<3>()));
-
- // Initiate a Read() on the data source, but don't allow the
- // message loop to run.
- data_source_->Read(
- 0, 10, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(static_cast<BufferedDataSourceTest*>(this))));
-
- // Call Abort() with the read pending.
- EXPECT_CALL(*this, ReadCallback(-1));
- EXPECT_CALL(*loader_, Stop());
- data_source_->Abort();
-
- // Verify that Read()'s after the Abort() issue callback with an error.
- EXPECT_CALL(*this, ReadCallback(-1));
- data_source_->Read(
- 0, 10, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(static_cast<BufferedDataSourceTest*>(this))));
-
- // Stop() the data source like normal.
- data_source_->Stop(media::NewExpectedClosure());
-
- // Allow cleanup task to run.
- message_loop_->RunAllPending();
-
- // Verify that Read() was not called on the loader.
- EXPECT_FALSE(read_called);
-}
-
-// Test that we only allow a limited number of cache misses for a
-// single Read() request.
-TEST_F(BufferedDataSourceTest, BoundedCacheMisses) {
- InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
-
- ReadDataSourceAlwaysCacheMiss(0, 10);
-
- StopDataSource();
-}
-
-// TODO(scherkus): de-dupe from buffered_resource_loader_unittest.cc
-ACTION_P(RequestCanceled, loader) {
- WebURLError error;
- error.reason = net::ERR_ABORTED;
- error.domain = WebString::fromUTF8(net::kErrorDomain);
- loader->didFail(NULL, error);
-}
-
-// A more realistic BufferedDataSource that uses BufferedResourceLoader instead
-// of a mocked version but injects a MockWebURLLoader.
-//
-// TODO(scherkus): re-write these tests to use this class then drop the "2"
-// suffix.
-class MockBufferedDataSource2 : public BufferedDataSource {
- public:
- MockBufferedDataSource2(MessageLoop* message_loop, WebFrame* frame)
- : BufferedDataSource(message_loop, frame, new media::MediaLog()),
- url_loader_(NULL) {
- }
-
- virtual base::TimeDelta GetTimeoutMilliseconds() {
- return base::TimeDelta::FromMilliseconds(
- TestTimeouts::tiny_timeout_ms());
- }
-
- virtual BufferedResourceLoader* CreateResourceLoader(int64 first_position,
- int64 last_position) {
- loader_ = BufferedDataSource::CreateResourceLoader(first_position,
- last_position);
-
- url_loader_ = new NiceMock<MockWebURLLoader>();
- ON_CALL(*url_loader_, cancel())
- .WillByDefault(RequestCanceled(loader_));
-
- loader_->SetURLLoaderForTest(url_loader_);
- return loader_;
- }
-
- const scoped_refptr<BufferedResourceLoader>& loader() { return loader_; }
- NiceMock<MockWebURLLoader>* url_loader() { return url_loader_; }
-
- private:
- scoped_refptr<BufferedResourceLoader> loader_;
- NiceMock<MockWebURLLoader>* url_loader_;
-
- DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource2);
-};
-
-class BufferedDataSourceTest2 : public testing::Test {
- public:
- BufferedDataSourceTest2()
- : view_(WebView::create(NULL)),
- message_loop_(MessageLoop::current()) {
- view_->initializeMainFrame(&client_);
- }
-
- virtual ~BufferedDataSourceTest2() {
- view_->close();
- }
-
- void InitializeDataSource(const char* url) {
- gurl_ = GURL(url);
-
- data_source_ = new MockBufferedDataSource2(message_loop_,
- view_->mainFrame());
- data_source_->set_host(&host_);
- data_source_->Initialize(url,
- media::NewExpectedStatusCB(media::PIPELINE_OK));
- message_loop_->RunAllPending();
-
- // Simulate 206 response for a 5,000,000 byte length file.
- WebURLResponse response(gurl_);
- response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
- WebString::fromUTF8("bytes"));
- response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
- WebString::fromUTF8("bytes 0-4999999/5000000"));
- response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
- WebString::fromUTF8("5000000"));
- response.setExpectedContentLength(5000000);
- response.setHTTPStatusCode(206);
-
- // We should receive corresponding information about the media resource.
- EXPECT_CALL(host_, SetLoaded(false));
- EXPECT_CALL(host_, SetTotalBytes(5000000));
- EXPECT_CALL(host_, SetBufferedBytes(0));
-
- data_source_->loader()->didReceiveResponse(data_source_->url_loader(),
- response);
-
- message_loop_->RunAllPending();
- }
-
- void StopDataSource() {
- data_source_->Stop(media::NewExpectedClosure());
- message_loop_->RunAllPending();
- }
-
- MOCK_METHOD1(ReadCallback, void(size_t size));
- media::DataSource::ReadCallback NewReadCallback(size_t size) {
- EXPECT_CALL(*this, ReadCallback(size));
- return base::Bind(&BufferedDataSourceTest2::ReadCallback,
- base::Unretained(this));
- }
-
- // Accessors for private variables on |data_source_|.
- media::Preload preload() { return data_source_->preload_; }
- BufferedResourceLoader::DeferStrategy defer_strategy() {
- return data_source_->loader()->defer_strategy_;
- }
- int data_source_bitrate() { return data_source_->bitrate_; }
- int data_source_playback_rate() { return data_source_->playback_rate_; }
- int loader_bitrate() { return data_source_->loader()->bitrate_; }
- int loader_playback_rate() { return data_source_->loader()->playback_rate_; }
-
- scoped_refptr<MockBufferedDataSource2> data_source_;
-
- GURL gurl_;
- MockWebFrameClient client_;
- WebView* view_;
-
- StrictMock<media::MockFilterHost> host_;
- MessageLoop* message_loop_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest2);
-};
-
-TEST_F(BufferedDataSourceTest2, Default) {
- InitializeDataSource("http://localhost/foo.webm");
+TEST_F(BufferedDataSourceTest, DefaultValues) {
+ InitializeWith206Response();
// Ensure we have sane values for default loading scenario.
EXPECT_EQ(media::AUTO, preload());
@@ -740,11 +387,12 @@ TEST_F(BufferedDataSourceTest2, Default) {
EXPECT_EQ(0, loader_bitrate());
EXPECT_EQ(0.0f, loader_playback_rate());
- StopDataSource();
+ EXPECT_TRUE(data_source_->loading());
+ Stop();
}
-TEST_F(BufferedDataSourceTest2, SetBitrate) {
- InitializeDataSource("http://localhost/foo.webm");
+TEST_F(BufferedDataSourceTest, SetBitrate) {
+ InitializeWith206Response();
data_source_->SetBitrate(1234);
message_loop_->RunAllPending();
@@ -752,22 +400,22 @@ TEST_F(BufferedDataSourceTest2, SetBitrate) {
EXPECT_EQ(1234, loader_bitrate());
// Read so far ahead to cause the loader to get recreated.
- BufferedResourceLoader* old_loader = data_source_->loader();
-
- uint8 buffer[1024];
- data_source_->Read(4000000, 1024, buffer,
- NewReadCallback(media::DataSource::kReadError));
- message_loop_->RunAllPending();
+ BufferedResourceLoader* old_loader = loader();
+ ExpectCreateResourceLoader();
+ ReadAt(kFarReadPosition);
+ Respond(response_generator_.Generate206(kFarReadPosition));
// Verify loader changed but still has same bitrate.
- EXPECT_NE(old_loader, data_source_->loader().get());
+ EXPECT_NE(old_loader, loader());
EXPECT_EQ(1234, loader_bitrate());
- StopDataSource();
+ EXPECT_TRUE(data_source_->loading());
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ Stop();
}
-TEST_F(BufferedDataSourceTest2, SetPlaybackRate) {
- InitializeDataSource("http://localhost/foo.webm");
+TEST_F(BufferedDataSourceTest, SetPlaybackRate) {
+ InitializeWith206Response();
data_source_->SetPlaybackRate(2.0f);
message_loop_->RunAllPending();
@@ -775,18 +423,36 @@ TEST_F(BufferedDataSourceTest2, SetPlaybackRate) {
EXPECT_EQ(2.0f, loader_playback_rate());
// Read so far ahead to cause the loader to get recreated.
- BufferedResourceLoader* old_loader = data_source_->loader();
+ BufferedResourceLoader* old_loader = loader();
+ ExpectCreateResourceLoader();
+ ReadAt(kFarReadPosition);
+ Respond(response_generator_.Generate206(kFarReadPosition));
- uint8 buffer[1024];
- data_source_->Read(4000000, 1024, buffer,
- NewReadCallback(media::DataSource::kReadError));
- message_loop_->RunAllPending();
+ // Verify loader changed but still has same playback rate.
+ EXPECT_NE(old_loader, loader());
- // Verify loader changed but still has same bitrate.
- EXPECT_NE(old_loader, data_source_->loader().get());
- EXPECT_EQ(2.0f, loader_playback_rate());
+ EXPECT_TRUE(data_source_->loading());
+ EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
+ Stop();
+}
+
+TEST_F(BufferedDataSourceTest, Read) {
+ InitializeWith206Response();
+
+ ReadAt(0);
+
+ // When the read completes we'll update our network status.
+ EXPECT_CALL(host_, SetBufferedBytes(kDataSize));
+ EXPECT_CALL(host_, SetNetworkActivity(true));
+ EXPECT_CALL(*this, ReadCallback(kDataSize));
+ FinishRead();
+
+ // During teardown we'll also report our final network status.
+ EXPECT_CALL(host_, SetBufferedBytes(kDataSize));
+ EXPECT_CALL(host_, SetNetworkActivity(false));
- StopDataSource();
+ EXPECT_TRUE(data_source_->loading());
+ Stop();
}
} // namespace webkit_media
diff --git a/webkit/media/buffered_resource_loader.h b/webkit/media/buffered_resource_loader.h
index e92eb37..4399d00 100644
--- a/webkit/media/buffered_resource_loader.h
+++ b/webkit/media/buffered_resource_loader.h
@@ -173,7 +173,7 @@ class BufferedResourceLoader
virtual ~BufferedResourceLoader();
private:
- friend class BufferedDataSourceTest2;
+ friend class BufferedDataSourceTest;
friend class BufferedResourceLoaderTest;
// Updates the |buffer_|'s forward and backward capacities.
diff --git a/webkit/media/test_response_generator.cc b/webkit/media/test_response_generator.cc
new file mode 100644
index 0000000..b3138c0
--- /dev/null
+++ b/webkit/media/test_response_generator.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 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 "webkit/media/test_response_generator.h"
+
+#include "base/format_macros.h"
+#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
+#include "net/base/net_errors.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
+
+using WebKit::WebString;
+using WebKit::WebURLError;
+using WebKit::WebURLResponse;
+
+namespace webkit_media {
+
+TestResponseGenerator::TestResponseGenerator(const GURL& gurl,
+ int64 content_length)
+ : gurl_(gurl),
+ content_length_(content_length) {
+}
+
+WebURLError TestResponseGenerator::GenerateError() {
+ WebURLError error;
+ error.reason = net::ERR_ABORTED;
+ error.domain = WebString::fromUTF8(net::kErrorDomain);
+ return error;
+}
+
+WebURLResponse TestResponseGenerator::Generate200() {
+ WebURLResponse response(gurl_);
+ response.setHTTPStatusCode(200);
+
+ response.setHTTPHeaderField(
+ WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8(base::Int64ToString(content_length_)));
+ response.setExpectedContentLength(content_length_);
+ return response;
+}
+
+WebURLResponse TestResponseGenerator::Generate206(int64 first_byte_offset) {
+ return Generate206(first_byte_offset, kNormal);
+}
+
+WebURLResponse TestResponseGenerator::Generate206(int64 first_byte_offset,
+ Flags flags) {
+ int64 range_content_length = content_length_ - first_byte_offset;
+ int64 last_byte_offset = content_length_ - 1;
+
+ WebURLResponse response(gurl_);
+ response.setHTTPStatusCode(206);
+
+ if ((flags & kNoAcceptRanges) == 0) {
+ response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
+ WebString::fromUTF8("bytes"));
+ }
+
+ if ((flags & kNoContentRange) == 0) {
+ std::string content_range = base::StringPrintf(
+ "bytes %" PRId64 "-%" PRId64 "/%" PRId64,
+ first_byte_offset, last_byte_offset, content_length_);
+ response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
+ WebString::fromUTF8(content_range));
+ }
+
+ if ((flags & kNoContentLength) == 0) {
+ response.setHTTPHeaderField(
+ WebString::fromUTF8("Content-Length"),
+ WebString::fromUTF8(base::Int64ToString(range_content_length)));
+ response.setExpectedContentLength(range_content_length);
+ }
+ return response;
+}
+
+WebURLResponse TestResponseGenerator::Generate404() {
+ WebURLResponse response(gurl_);
+ response.setHTTPStatusCode(404);
+ return response;
+}
+
+} // namespace webkit_media
diff --git a/webkit/media/test_response_generator.h b/webkit/media/test_response_generator.h
new file mode 100644
index 0000000..fbdf5a8
--- /dev/null
+++ b/webkit/media/test_response_generator.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2011 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.
+
+#ifndef WEBKIT_MEDIA_TEST_RESPONSE_GENERATOR_H_
+#define WEBKIT_MEDIA_TEST_RESPONSE_GENERATOR_H_
+
+#include "base/basictypes.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
+
+namespace webkit_media {
+
+// Generates WebURLErrors and WebURLResponses suitable for testing purposes.
+class TestResponseGenerator {
+ public:
+ enum Flags {
+ kNormal = 0,
+ kNoAcceptRanges = 1 << 0, // Don't include Accept-Ranges in 206 response.
+ kNoContentRange = 1 << 1, // Don't include Content-Range in 206 response.
+ kNoContentLength = 1 << 2, // Don't include Content-Length in 206 response.
+ };
+
+ // Build an HTTP response generator for the given URL. |content_length| is
+ // used to generate Content-Length and Content-Range headers.
+ TestResponseGenerator(const GURL& gurl, int64 content_length);
+
+ // Generates a WebURLError object.
+ WebKit::WebURLError GenerateError();
+
+ // Generates a regular HTTP 200 response.
+ WebKit::WebURLResponse Generate200();
+
+ // Generates a regular HTTP 206 response starting from |first_byte_offset|
+ // until the end of the resource.
+ WebKit::WebURLResponse Generate206(int64 first_byte_offset);
+
+ // Generates a custom HTTP 206 response starting from |first_byte_offset|
+ // until the end of the resource. You can tweak what gets included in the
+ // headers via |flags|.
+ WebKit::WebURLResponse Generate206(int64 first_byte_offset, Flags flags);
+
+ // Generates a regular HTTP 404 response.
+ WebKit::WebURLResponse Generate404();
+
+ const GURL& gurl() { return gurl_; }
+ int64 content_length() { return content_length_; }
+
+ private:
+ GURL gurl_;
+ int64 content_length_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResponseGenerator);
+};
+
+} // namespace webkit_media
+
+#endif // WEBKIT_MEDIA_TEST_RESPONSE_GENERATOR_H_