IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / renderer / media / buffered_data_source_unittest.cc
blobe4869070928286580d28a336b7cf5e82b69d1f1c
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "content/renderer/media/buffered_data_source.h"
8 #include "content/renderer/media/test_response_generator.h"
9 #include "content/test/mock_webframeclient.h"
10 #include "content/test/mock_weburlloader.h"
11 #include "media/base/media_log.h"
12 #include "media/base/mock_data_source_host.h"
13 #include "media/base/mock_filters.h"
14 #include "media/base/test_helpers.h"
15 #include "third_party/WebKit/public/platform/WebURLResponse.h"
16 #include "third_party/WebKit/public/web/WebFrame.h"
17 #include "third_party/WebKit/public/web/WebView.h"
19 using ::testing::_;
20 using ::testing::Assign;
21 using ::testing::Invoke;
22 using ::testing::InSequence;
23 using ::testing::NiceMock;
24 using ::testing::StrictMock;
26 using blink::WebFrame;
27 using blink::WebString;
28 using blink::WebURLLoader;
29 using blink::WebURLResponse;
30 using blink::WebView;
32 namespace content {
34 // Overrides CreateResourceLoader() to permit injecting a MockWebURLLoader.
35 // Also keeps track of whether said MockWebURLLoader is actively loading.
36 class MockBufferedDataSource : public BufferedDataSource {
37 public:
38 MockBufferedDataSource(
39 const scoped_refptr<base::MessageLoopProxy>& message_loop,
40 WebFrame* frame)
41 : BufferedDataSource(message_loop, frame, new media::MediaLog(),
42 base::Bind(&MockBufferedDataSource::set_downloading,
43 base::Unretained(this))),
44 downloading_(false),
45 loading_(false) {
47 virtual ~MockBufferedDataSource() {}
49 MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*(int64, int64));
50 BufferedResourceLoader* CreateMockResourceLoader(int64 first_byte_position,
51 int64 last_byte_position) {
52 CHECK(!loading_) << "Previous resource load wasn't cancelled";
54 BufferedResourceLoader* loader =
55 BufferedDataSource::CreateResourceLoader(first_byte_position,
56 last_byte_position);
58 // Keep track of active loading state via loadAsynchronously() and cancel().
59 NiceMock<MockWebURLLoader>* url_loader = new NiceMock<MockWebURLLoader>();
60 ON_CALL(*url_loader, loadAsynchronously(_, _))
61 .WillByDefault(Assign(&loading_, true));
62 ON_CALL(*url_loader, cancel())
63 .WillByDefault(Assign(&loading_, false));
65 // |test_loader_| will be used when Start() is called.
66 loader->test_loader_ = scoped_ptr<WebURLLoader>(url_loader);
67 return loader;
70 bool loading() { return loading_; }
71 void set_loading(bool loading) { loading_ = loading; }
72 bool downloading() { return downloading_; }
73 void set_downloading(bool downloading) { downloading_ = downloading; }
75 private:
76 // Whether the resource is downloading or deferred.
77 bool downloading_;
79 // Whether the resource load has starting loading but yet to been cancelled.
80 bool loading_;
82 DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource);
85 static const int64 kFileSize = 5000000;
86 static const int64 kFarReadPosition = 4000000;
87 static const int kDataSize = 1024;
89 static const char kHttpUrl[] = "http://localhost/foo.webm";
90 static const char kFileUrl[] = "file:///tmp/bar.webm";
92 class BufferedDataSourceTest : public testing::Test {
93 public:
94 BufferedDataSourceTest()
95 : view_(WebView::create(NULL)), frame_(WebFrame::create(&client_)) {
96 view_->setMainFrame(frame_);
98 data_source_.reset(new MockBufferedDataSource(
99 message_loop_.message_loop_proxy(), view_->mainFrame()));
100 data_source_->set_host(&host_);
103 virtual ~BufferedDataSourceTest() {
104 view_->close();
105 frame_->close();
108 MOCK_METHOD1(OnInitialize, void(bool));
110 void Initialize(const char* url, bool expected) {
111 GURL gurl(url);
112 response_generator_.reset(new TestResponseGenerator(gurl, kFileSize));
114 ExpectCreateResourceLoader();
115 EXPECT_CALL(*this, OnInitialize(expected));
116 data_source_->Initialize(
117 gurl, BufferedResourceLoader::kUnspecified, base::Bind(
118 &BufferedDataSourceTest::OnInitialize, base::Unretained(this)));
119 message_loop_.RunUntilIdle();
121 bool is_http = gurl.SchemeIs(kHttpScheme) || gurl.SchemeIs(kHttpsScheme);
122 EXPECT_EQ(data_source_->downloading(), is_http);
125 // Helper to initialize tests with a valid 206 response.
126 void InitializeWith206Response() {
127 Initialize(kHttpUrl, true);
129 EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
130 Respond(response_generator_->Generate206(0));
133 // Helper to initialize tests with a valid file:// response.
134 void InitializeWithFileResponse() {
135 Initialize(kFileUrl, true);
137 EXPECT_CALL(host_, SetTotalBytes(kFileSize));
138 EXPECT_CALL(host_, AddBufferedByteRange(0, kFileSize));
139 Respond(response_generator_->GenerateFileResponse(0));
142 // Stops any active loaders and shuts down the data source.
144 // This typically happens when the page is closed and for our purposes is
145 // appropriate to do when tearing down a test.
146 void Stop() {
147 if (data_source_->loading()) {
148 loader()->didFail(url_loader(), response_generator_->GenerateError());
149 message_loop_.RunUntilIdle();
152 data_source_->Stop(media::NewExpectedClosure());
153 message_loop_.RunUntilIdle();
156 void ExpectCreateResourceLoader() {
157 EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
158 .WillOnce(Invoke(data_source_.get(),
159 &MockBufferedDataSource::CreateMockResourceLoader));
160 message_loop_.RunUntilIdle();
163 void Respond(const WebURLResponse& response) {
164 loader()->didReceiveResponse(url_loader(), response);
165 message_loop_.RunUntilIdle();
168 void ReceiveData(int size) {
169 scoped_ptr<char[]> data(new char[size]);
170 memset(data.get(), 0xA5, size); // Arbitrary non-zero value.
172 loader()->didReceiveData(url_loader(), data.get(), size, size);
173 message_loop_.RunUntilIdle();
176 void FinishLoading() {
177 data_source_->set_loading(false);
178 loader()->didFinishLoading(url_loader(), 0);
179 message_loop_.RunUntilIdle();
182 MOCK_METHOD1(ReadCallback, void(int size));
184 void ReadAt(int64 position) {
185 data_source_->Read(position, kDataSize, buffer_,
186 base::Bind(&BufferedDataSourceTest::ReadCallback,
187 base::Unretained(this)));
188 message_loop_.RunUntilIdle();
191 // Accessors for private variables on |data_source_|.
192 BufferedResourceLoader* loader() {
193 return data_source_->loader_.get();
195 WebURLLoader* url_loader() {
196 return loader()->active_loader_->loader_.get();
199 Preload preload() { return data_source_->preload_; }
200 BufferedResourceLoader::DeferStrategy defer_strategy() {
201 return loader()->defer_strategy_;
203 int data_source_bitrate() { return data_source_->bitrate_; }
204 int data_source_playback_rate() { return data_source_->playback_rate_; }
205 int loader_bitrate() { return loader()->bitrate_; }
206 int loader_playback_rate() { return loader()->playback_rate_; }
208 scoped_ptr<MockBufferedDataSource> data_source_;
210 scoped_ptr<TestResponseGenerator> response_generator_;
211 MockWebFrameClient client_;
212 WebView* view_;
213 WebFrame* frame_;
215 StrictMock<media::MockDataSourceHost> host_;
216 base::MessageLoop message_loop_;
218 private:
219 // Used for calling BufferedDataSource::Read().
220 uint8 buffer_[kDataSize];
222 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
225 TEST_F(BufferedDataSourceTest, Range_Supported) {
226 Initialize(kHttpUrl, true);
228 EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
229 Respond(response_generator_->Generate206(0));
231 EXPECT_TRUE(data_source_->loading());
232 EXPECT_FALSE(data_source_->IsStreaming());
233 Stop();
236 TEST_F(BufferedDataSourceTest, Range_InstanceSizeUnknown) {
237 Initialize(kHttpUrl, true);
239 Respond(response_generator_->Generate206(
240 0, TestResponseGenerator::kNoContentRangeInstanceSize));
242 EXPECT_TRUE(data_source_->loading());
243 EXPECT_TRUE(data_source_->IsStreaming());
244 Stop();
247 TEST_F(BufferedDataSourceTest, Range_NotFound) {
248 Initialize(kHttpUrl, false);
249 Respond(response_generator_->Generate404());
251 EXPECT_FALSE(data_source_->loading());
252 Stop();
255 TEST_F(BufferedDataSourceTest, Range_NotSupported) {
256 Initialize(kHttpUrl, true);
257 EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
258 Respond(response_generator_->Generate200());
260 EXPECT_TRUE(data_source_->loading());
261 EXPECT_TRUE(data_source_->IsStreaming());
262 Stop();
265 // Special carve-out for Apache versions that choose to return a 200 for
266 // Range:0- ("because it's more efficient" than a 206)
267 TEST_F(BufferedDataSourceTest, Range_SupportedButReturned200) {
268 Initialize(kHttpUrl, true);
269 EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
270 WebURLResponse response = response_generator_->Generate200();
271 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
272 WebString::fromUTF8("bytes"));
273 Respond(response);
275 EXPECT_TRUE(data_source_->loading());
276 EXPECT_FALSE(data_source_->IsStreaming());
277 Stop();
280 TEST_F(BufferedDataSourceTest, Range_MissingContentRange) {
281 Initialize(kHttpUrl, false);
282 Respond(response_generator_->Generate206(
283 0, TestResponseGenerator::kNoContentRange));
285 EXPECT_FALSE(data_source_->loading());
286 Stop();
289 TEST_F(BufferedDataSourceTest, Range_MissingContentLength) {
290 Initialize(kHttpUrl, true);
292 // It'll manage without a Content-Length response.
293 EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
294 Respond(response_generator_->Generate206(
295 0, TestResponseGenerator::kNoContentLength));
297 EXPECT_TRUE(data_source_->loading());
298 EXPECT_FALSE(data_source_->IsStreaming());
299 Stop();
302 TEST_F(BufferedDataSourceTest, Range_WrongContentRange) {
303 Initialize(kHttpUrl, false);
305 // Now it's done and will fail.
306 Respond(response_generator_->Generate206(1337));
308 EXPECT_FALSE(data_source_->loading());
309 Stop();
312 // Test the case where the initial response from the server indicates that
313 // Range requests are supported, but a later request prove otherwise.
314 TEST_F(BufferedDataSourceTest, Range_ServerLied) {
315 InitializeWith206Response();
317 // Read causing a new request to be made -- we'll expect it to error.
318 ExpectCreateResourceLoader();
319 ReadAt(kFarReadPosition);
321 // Return a 200 in response to a range request.
322 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
323 Respond(response_generator_->Generate200());
325 EXPECT_FALSE(data_source_->loading());
326 Stop();
329 TEST_F(BufferedDataSourceTest, Http_AbortWhileReading) {
330 InitializeWith206Response();
332 // Make sure there's a pending read -- we'll expect it to error.
333 ReadAt(0);
335 // Abort!!!
336 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
337 data_source_->Abort();
338 message_loop_.RunUntilIdle();
340 EXPECT_FALSE(data_source_->loading());
341 Stop();
344 TEST_F(BufferedDataSourceTest, File_AbortWhileReading) {
345 InitializeWithFileResponse();
347 // Make sure there's a pending read -- we'll expect it to error.
348 ReadAt(0);
350 // Abort!!!
351 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
352 data_source_->Abort();
353 message_loop_.RunUntilIdle();
355 EXPECT_FALSE(data_source_->loading());
356 Stop();
359 TEST_F(BufferedDataSourceTest, Http_Retry) {
360 InitializeWith206Response();
362 // Read to advance our position.
363 EXPECT_CALL(*this, ReadCallback(kDataSize));
364 EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
365 ReadAt(0);
366 ReceiveData(kDataSize);
368 // Issue a pending read but terminate the connection to force a retry.
369 ReadAt(kDataSize);
370 ExpectCreateResourceLoader();
371 FinishLoading();
372 Respond(response_generator_->Generate206(kDataSize));
374 // Complete the read.
375 EXPECT_CALL(*this, ReadCallback(kDataSize));
376 EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, (kDataSize * 2) - 1));
377 ReceiveData(kDataSize);
379 EXPECT_TRUE(data_source_->loading());
380 Stop();
383 TEST_F(BufferedDataSourceTest, File_Retry) {
384 InitializeWithFileResponse();
386 // Read to advance our position.
387 EXPECT_CALL(*this, ReadCallback(kDataSize));
388 ReadAt(0);
389 ReceiveData(kDataSize);
391 // Issue a pending read but terminate the connection to force a retry.
392 ReadAt(kDataSize);
393 ExpectCreateResourceLoader();
394 FinishLoading();
395 Respond(response_generator_->GenerateFileResponse(kDataSize));
397 // Complete the read.
398 EXPECT_CALL(*this, ReadCallback(kDataSize));
399 ReceiveData(kDataSize);
401 EXPECT_TRUE(data_source_->loading());
402 Stop();
405 TEST_F(BufferedDataSourceTest, Http_TooManyRetries) {
406 InitializeWith206Response();
408 // Make sure there's a pending read -- we'll expect it to error.
409 ReadAt(0);
411 // It'll try three times.
412 ExpectCreateResourceLoader();
413 FinishLoading();
414 Respond(response_generator_->Generate206(0));
416 ExpectCreateResourceLoader();
417 FinishLoading();
418 Respond(response_generator_->Generate206(0));
420 ExpectCreateResourceLoader();
421 FinishLoading();
422 Respond(response_generator_->Generate206(0));
424 // It'll error after this.
425 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
426 FinishLoading();
428 EXPECT_FALSE(data_source_->loading());
429 Stop();
432 TEST_F(BufferedDataSourceTest, File_TooManyRetries) {
433 InitializeWithFileResponse();
435 // Make sure there's a pending read -- we'll expect it to error.
436 ReadAt(0);
438 // It'll try three times.
439 ExpectCreateResourceLoader();
440 FinishLoading();
441 Respond(response_generator_->GenerateFileResponse(0));
443 ExpectCreateResourceLoader();
444 FinishLoading();
445 Respond(response_generator_->GenerateFileResponse(0));
447 ExpectCreateResourceLoader();
448 FinishLoading();
449 Respond(response_generator_->GenerateFileResponse(0));
451 // It'll error after this.
452 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
453 FinishLoading();
455 EXPECT_FALSE(data_source_->loading());
456 Stop();
459 TEST_F(BufferedDataSourceTest, File_InstanceSizeUnknown) {
460 Initialize(kFileUrl, false);
461 EXPECT_FALSE(data_source_->downloading());
463 Respond(response_generator_->GenerateFileResponse(-1));
465 EXPECT_FALSE(data_source_->loading());
466 Stop();
469 TEST_F(BufferedDataSourceTest, File_Successful) {
470 InitializeWithFileResponse();
472 EXPECT_TRUE(data_source_->loading());
473 EXPECT_FALSE(data_source_->IsStreaming());
474 Stop();
477 static void SetTrue(bool* value) {
478 *value = true;
481 // This test makes sure that Stop() does not require a task to run on
482 // |message_loop_| before it calls its callback. This prevents accidental
483 // introduction of a pipeline teardown deadlock. The pipeline owner blocks
484 // the render message loop while waiting for Stop() to complete. Since this
485 // object runs on the render message loop, Stop() will not complete if it
486 // requires a task to run on the the message loop that is being blocked.
487 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
488 InitializeWith206Response();
490 // Stop() the data source, using a callback that lets us verify that it was
491 // called before Stop() returns. This is to make sure that the callback does
492 // not require |message_loop_| to execute tasks before being called.
493 bool stop_done_called = false;
494 EXPECT_TRUE(data_source_->loading());
495 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called));
497 // Verify that the callback was called inside the Stop() call.
498 EXPECT_TRUE(stop_done_called);
499 message_loop_.RunUntilIdle();
502 TEST_F(BufferedDataSourceTest, StopDuringRead) {
503 InitializeWith206Response();
505 uint8 buffer[256];
506 data_source_->Read(0, arraysize(buffer), buffer, base::Bind(
507 &BufferedDataSourceTest::ReadCallback, base::Unretained(this)));
509 // The outstanding read should fail before the stop callback runs.
511 InSequence s;
512 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
513 data_source_->Stop(media::NewExpectedClosure());
515 message_loop_.RunUntilIdle();
518 TEST_F(BufferedDataSourceTest, DefaultValues) {
519 InitializeWith206Response();
521 // Ensure we have sane values for default loading scenario.
522 EXPECT_EQ(AUTO, preload());
523 EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
525 EXPECT_EQ(0, data_source_bitrate());
526 EXPECT_EQ(0.0f, data_source_playback_rate());
527 EXPECT_EQ(0, loader_bitrate());
528 EXPECT_EQ(0.0f, loader_playback_rate());
530 EXPECT_TRUE(data_source_->loading());
531 Stop();
534 TEST_F(BufferedDataSourceTest, SetBitrate) {
535 InitializeWith206Response();
537 data_source_->SetBitrate(1234);
538 message_loop_.RunUntilIdle();
539 EXPECT_EQ(1234, data_source_bitrate());
540 EXPECT_EQ(1234, loader_bitrate());
542 // Read so far ahead to cause the loader to get recreated.
543 BufferedResourceLoader* old_loader = loader();
544 ExpectCreateResourceLoader();
545 ReadAt(kFarReadPosition);
546 Respond(response_generator_->Generate206(kFarReadPosition));
548 // Verify loader changed but still has same bitrate.
549 EXPECT_NE(old_loader, loader());
550 EXPECT_EQ(1234, loader_bitrate());
552 EXPECT_TRUE(data_source_->loading());
553 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
554 Stop();
557 TEST_F(BufferedDataSourceTest, MediaPlaybackRateChanged) {
558 InitializeWith206Response();
560 data_source_->MediaPlaybackRateChanged(2.0f);
561 message_loop_.RunUntilIdle();
562 EXPECT_EQ(2.0f, data_source_playback_rate());
563 EXPECT_EQ(2.0f, loader_playback_rate());
565 // Read so far ahead to cause the loader to get recreated.
566 BufferedResourceLoader* old_loader = loader();
567 ExpectCreateResourceLoader();
568 ReadAt(kFarReadPosition);
569 Respond(response_generator_->Generate206(kFarReadPosition));
571 // Verify loader changed but still has same playback rate.
572 EXPECT_NE(old_loader, loader());
574 EXPECT_TRUE(data_source_->loading());
575 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
576 Stop();
579 TEST_F(BufferedDataSourceTest, Http_Read) {
580 InitializeWith206Response();
582 ReadAt(0);
584 // Receive first half of the read.
585 EXPECT_CALL(host_, AddBufferedByteRange(0, (kDataSize / 2) - 1));
586 ReceiveData(kDataSize / 2);
588 // Receive last half of the read.
589 EXPECT_CALL(*this, ReadCallback(kDataSize));
590 EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
591 ReceiveData(kDataSize / 2);
593 EXPECT_TRUE(data_source_->downloading());
594 Stop();
597 TEST_F(BufferedDataSourceTest, Http_Read_Seek) {
598 InitializeWith206Response();
600 // Read a bit from the beginning.
601 ReadAt(0);
602 EXPECT_CALL(*this, ReadCallback(kDataSize));
603 EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
604 ReceiveData(kDataSize);
606 // Simulate a seek by reading a bit beyond kDataSize.
607 ReadAt(kDataSize * 2);
609 // We receive data leading up to but not including our read.
610 EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2 - 1));
611 ReceiveData(kDataSize);
613 // We now receive the rest of the data for our read.
614 EXPECT_CALL(*this, ReadCallback(kDataSize));
615 EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3 - 1));
616 ReceiveData(kDataSize);
618 EXPECT_TRUE(data_source_->downloading());
619 Stop();
622 TEST_F(BufferedDataSourceTest, File_Read) {
623 InitializeWithFileResponse();
625 ReadAt(0);
627 // Receive first half of the read but no buffering update.
628 ReceiveData(kDataSize / 2);
630 // Receive last half of the read but no buffering update.
631 EXPECT_CALL(*this, ReadCallback(kDataSize));
632 ReceiveData(kDataSize / 2);
634 Stop();
637 TEST_F(BufferedDataSourceTest, Http_FinishLoading) {
638 InitializeWith206Response();
640 EXPECT_TRUE(data_source_->downloading());
641 FinishLoading();
642 EXPECT_FALSE(data_source_->downloading());
644 Stop();
647 TEST_F(BufferedDataSourceTest, File_FinishLoading) {
648 InitializeWithFileResponse();
650 EXPECT_FALSE(data_source_->downloading());
651 FinishLoading();
652 EXPECT_FALSE(data_source_->downloading());
654 Stop();
657 } // namespace content