Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(894)

Side by Side Diff: webkit/media/buffered_data_source_unittest.cc

Issue 8649002: Rewrite BufferedDataSource tests to use real BufferedResourceLoader objects. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: vrk comments Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/media/buffered_data_source.h ('k') | webkit/media/buffered_resource_loader.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm>
6
7 #include "base/bind.h" 5 #include "base/bind.h"
8 #include "base/test/test_timeouts.h"
9 #include "media/base/media_log.h" 6 #include "media/base/media_log.h"
10 #include "media/base/mock_callback.h" 7 #include "media/base/mock_callback.h"
11 #include "media/base/mock_filter_host.h" 8 #include "media/base/mock_filter_host.h"
12 #include "media/base/mock_filters.h" 9 #include "media/base/mock_filters.h"
13 #include "net/base/net_errors.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
17 #include "webkit/media/buffered_data_source.h" 12 #include "webkit/media/buffered_data_source.h"
18 #include "webkit/mocks/mock_webframeclient.h" 13 #include "webkit/mocks/mock_webframeclient.h"
19 #include "webkit/mocks/mock_weburlloader.h" 14 #include "webkit/mocks/mock_weburlloader.h"
15 #include "webkit/media/test_response_generator.h"
20 16
21 using ::testing::_; 17 using ::testing::_;
22 using ::testing::Assign; 18 using ::testing::Assign;
23 using ::testing::AtLeast;
24 using ::testing::DeleteArg;
25 using ::testing::DoAll;
26 using ::testing::InSequence;
27 using ::testing::Invoke; 19 using ::testing::Invoke;
28 using ::testing::InvokeWithoutArgs; 20 using ::testing::Mock;
29 using ::testing::NotNull;
30 using ::testing::Return;
31 using ::testing::ReturnRef;
32 using ::testing::SetArgumentPointee;
33 using ::testing::StrictMock; 21 using ::testing::StrictMock;
34 using ::testing::NiceMock; 22 using ::testing::NiceMock;
35 using ::testing::WithArgs;
36 23
37 using WebKit::WebFrame; 24 using WebKit::WebFrame;
38 using WebKit::WebString; 25 using WebKit::WebURLLoader;
39 using WebKit::WebURLError;
40 using WebKit::WebURLResponse; 26 using WebKit::WebURLResponse;
41 using WebKit::WebView; 27 using WebKit::WebView;
42 28
43 using webkit_glue::MockWebFrameClient; 29 using webkit_glue::MockWebFrameClient;
44 using webkit_glue::MockWebURLLoader; 30 using webkit_glue::MockWebURLLoader;
45 31
46 namespace webkit_media { 32 namespace webkit_media {
47 33
48 static const char* kHttpUrl = "http://test"; 34 // Overrides CreateResourceLoader() to permit injecting a MockWebURLLoader.
49 static const char* kFileUrl = "file://test"; 35 // Also keeps track of whether said MockWebURLLoader is actively loading.
50 static const int kDataSize = 1024;
51 static const int kMaxCacheMissesBeforeFailTest = 20;
52
53 enum NetworkState {
54 NONE,
55 LOADED,
56 LOADING
57 };
58
59 // A mock BufferedDataSource to inject mock BufferedResourceLoader through
60 // CreateResourceLoader() method.
61 class MockBufferedDataSource : public BufferedDataSource { 36 class MockBufferedDataSource : public BufferedDataSource {
62 public: 37 public:
63 MockBufferedDataSource(MessageLoop* message_loop, WebFrame* frame) 38 MockBufferedDataSource(MessageLoop* message_loop, WebFrame* frame)
64 : BufferedDataSource(message_loop, frame, new media::MediaLog()) { 39 : BufferedDataSource(message_loop, frame, new media::MediaLog()),
65 } 40 loading_(false) {
66 41 }
67 virtual base::TimeDelta GetTimeoutMilliseconds() { 42
68 return base::TimeDelta::FromMilliseconds( 43 MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*(int64, int64));
69 TestTimeouts::tiny_timeout_ms()); 44 BufferedResourceLoader* CreateMockResourceLoader(int64 first_byte_position,
70 } 45 int64 last_byte_position) {
71 46 CHECK(!loading_) << "Previous resource load wasn't cancelled";
72 MOCK_METHOD2(CreateResourceLoader, 47
73 BufferedResourceLoader*(int64 first_position, 48 BufferedResourceLoader* loader =
74 int64 last_position)); 49 BufferedDataSource::CreateResourceLoader(first_byte_position,
50 last_byte_position);
51
52 // Keep track of active loading state via loadAsynchronously() and cancel().
53 NiceMock<MockWebURLLoader>* url_loader = new NiceMock<MockWebURLLoader>();
54 ON_CALL(*url_loader, loadAsynchronously(_, _))
55 .WillByDefault(Assign(&loading_, true));
56 ON_CALL(*url_loader, cancel())
57 .WillByDefault(Assign(&loading_, false));
58
59 // TODO(scherkus): this is a real leak detected by http://crbug.com/100914
60 // but the fix will have to wait for a more invasive follow up patch.
61 //
62 // If you're curious what the fix is, we no longer need the reference
63 // counting added to BufferedResourceLoader in r23274 since we started
64 // using WebURLLoader in r69429.
65 Mock::AllowLeak(url_loader);
66
67 loader->SetURLLoaderForTest(url_loader);
68 return loader;
69 }
70
71 bool loading() { return loading_; }
72 void set_loading(bool loading) { loading_ = loading; }
75 73
76 private: 74 private:
75 // Whether the resource load has starting loading but yet to been cancelled.
76 bool loading_;
77
77 DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource); 78 DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource);
78 }; 79 };
79 80
80 class MockBufferedResourceLoader : public BufferedResourceLoader { 81 static const int64 kFileSize = 5000000;
81 public: 82 static const int64 kFarReadPosition = 4000000;
82 MockBufferedResourceLoader() 83 static const size_t kDataSize = 1024;
83 : BufferedResourceLoader(GURL(), 0, 0, kThresholdDefer,
84 0, 0, new media::MediaLog()) {
85 }
86
87 MOCK_METHOD3(Start, void(net::OldCompletionCallback* read_callback,
88 const base::Closure& network_callback,
89 WebFrame* frame));
90 MOCK_METHOD0(Stop, void());
91 MOCK_METHOD4(Read, void(int64 position, int read_size, uint8* buffer,
92 net::OldCompletionCallback* callback));
93 MOCK_METHOD0(content_length, int64());
94 MOCK_METHOD0(instance_size, int64());
95 MOCK_METHOD0(range_supported, bool());
96 MOCK_METHOD0(network_activity, bool());
97 MOCK_METHOD0(url, const GURL&());
98 MOCK_METHOD0(GetBufferedFirstBytePosition, int64());
99 MOCK_METHOD0(GetBufferedLastBytePosition, int64());
100
101 protected:
102 ~MockBufferedResourceLoader() {}
103
104 DISALLOW_COPY_AND_ASSIGN(MockBufferedResourceLoader);
105 };
106 84
107 class BufferedDataSourceTest : public testing::Test { 85 class BufferedDataSourceTest : public testing::Test {
108 public: 86 public:
109 BufferedDataSourceTest() 87 BufferedDataSourceTest()
110 : view_(WebView::create(NULL)) { 88 : response_generator_(GURL("http://localhost/foo.webm"), kFileSize),
89 view_(WebView::create(NULL)),
90 message_loop_(MessageLoop::current()) {
111 view_->initializeMainFrame(&client_); 91 view_->initializeMainFrame(&client_);
112 message_loop_ = MessageLoop::current(); 92
113 93 data_source_ = new MockBufferedDataSource(message_loop_,
114 for (size_t i = 0; i < sizeof(data_); ++i) { 94 view_->mainFrame());
115 data_[i] = i; 95 data_source_->set_host(&host_);
116 }
117 } 96 }
118 97
119 virtual ~BufferedDataSourceTest() { 98 virtual ~BufferedDataSourceTest() {
120 view_->close(); 99 view_->close();
121 } 100 }
122 101
123 void ExpectCreateAndStartResourceLoader(int start_error) { 102 void Initialize(media::PipelineStatus expected) {
103 ExpectCreateResourceLoader();
104 data_source_->Initialize(response_generator_.gurl().spec(),
105 media::NewExpectedStatusCB(expected));
106 message_loop_->RunAllPending();
107 }
108
109 // Helper to initialize tests with a valid 206 response.
110 void InitializeWith206Response() {
111 Initialize(media::PIPELINE_OK);
112
113 EXPECT_CALL(host_, SetLoaded(false));
114 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
115 EXPECT_CALL(host_, SetBufferedBytes(0));
116 Respond(response_generator_.Generate206(0));
117 }
118
119 // Stops any active loaders and shuts down the data source.
120 //
121 // This typically happens when the page is closed and for our purposes is
122 // appropriate to do when tearing down a test.
123 void Stop() {
124 if (data_source_->loading()) {
125 loader()->didFail(url_loader(), response_generator_.GenerateError());
126 message_loop_->RunAllPending();
127 }
128
129 data_source_->Stop(media::NewExpectedClosure());
130 message_loop_->RunAllPending();
131 }
132
133 void ExpectCreateResourceLoader() {
124 EXPECT_CALL(*data_source_, CreateResourceLoader(_, _)) 134 EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
125 .WillOnce(Return(loader_.get())); 135 .WillOnce(Invoke(data_source_.get(),
126 136 &MockBufferedDataSource::CreateMockResourceLoader));
127 EXPECT_CALL(*loader_, Start(NotNull(), _, NotNull())) 137 message_loop_->RunAllPending();
128 .WillOnce( 138 }
129 DoAll(Assign(&error_, start_error), 139
130 Invoke(this, 140 void Respond(const WebURLResponse& response) {
131 &BufferedDataSourceTest::InvokeStartCallback))); 141 loader()->didReceiveResponse(url_loader(), response);
132 } 142 message_loop_->RunAllPending();
133 143 }
134 void InitializeDataSource(const char* url, int error, 144
135 bool partial_response, int64 instance_size, 145 void FinishRead() {
136 NetworkState networkState) { 146 loader()->didReceiveData(url_loader(), data_, kDataSize, kDataSize);
137 // Saves the url first. 147 message_loop_->RunAllPending();
138 gurl_ = GURL(url); 148 }
139 149
140 data_source_ = new MockBufferedDataSource(MessageLoop::current(), 150 void FinishLoading() {
141 view_->mainFrame()); 151 data_source_->set_loading(false);
142 data_source_->set_host(&host_); 152 loader()->didFinishLoading(url_loader(), 0);
143 153 message_loop_->RunAllPending();
144 scoped_refptr<NiceMock<MockBufferedResourceLoader> > first_loader(
145 new NiceMock<MockBufferedResourceLoader>());
146
147 // Creates the mock loader to be injected.
148 loader_ = first_loader;
149
150 bool initialized_ok = (error == net::OK);
151 bool loaded = networkState == LOADED;
152 {
153 InSequence s;
154 ExpectCreateAndStartResourceLoader(error);
155
156 // In the case of an invalid partial response we expect a second loader
157 // to be created.
158 if (partial_response && (error == net::ERR_INVALID_RESPONSE)) {
159 // Verify that the initial loader is stopped.
160 EXPECT_CALL(*loader_, url())
161 .WillRepeatedly(ReturnRef(gurl_));
162 EXPECT_CALL(*loader_, Stop());
163
164 // Replace loader_ with a new instance.
165 loader_ = new NiceMock<MockBufferedResourceLoader>();
166
167 // Create and start. Make sure Start() is called on the new loader.
168 ExpectCreateAndStartResourceLoader(net::OK);
169
170 // Update initialization variable since we know the second loader will
171 // return OK.
172 initialized_ok = true;
173 }
174 }
175
176 // Attach a static function that deletes the memory referred by the
177 // "callback" parameter.
178 ON_CALL(*loader_, Read(_, _, _ , _))
179 .WillByDefault(DeleteArg<3>());
180
181 ON_CALL(*loader_, instance_size())
182 .WillByDefault(Return(instance_size));
183
184 // range_supported() return true if we expect to get a partial response.
185 ON_CALL(*loader_, range_supported())
186 .WillByDefault(Return(partial_response));
187
188 ON_CALL(*loader_, url())
189 .WillByDefault(ReturnRef(gurl_));
190 media::PipelineStatus expected_init_status = media::PIPELINE_OK;
191 if (initialized_ok) {
192 // Expected loaded or not.
193 EXPECT_CALL(host_, SetLoaded(loaded));
194
195 if (instance_size != -1)
196 EXPECT_CALL(host_, SetTotalBytes(instance_size));
197
198 if (loaded)
199 EXPECT_CALL(host_, SetBufferedBytes(instance_size));
200 else
201 EXPECT_CALL(host_, SetBufferedBytes(0));
202
203 if (!partial_response || instance_size == -1)
204 EXPECT_CALL(host_, SetStreaming(true));
205
206 } else {
207 expected_init_status = media::PIPELINE_ERROR_NETWORK;
208 EXPECT_CALL(*loader_, Stop());
209 }
210
211 // Actual initialization of the data source.
212 data_source_->Initialize(url,
213 media::NewExpectedStatusCB(expected_init_status));
214 message_loop_->RunAllPending();
215
216 if (initialized_ok) {
217 // Verify the size of the data source.
218 int64 size;
219 if (instance_size != -1 && (loaded || partial_response)) {
220 EXPECT_TRUE(data_source_->GetSize(&size));
221 EXPECT_EQ(instance_size, size);
222 } else {
223 EXPECT_TRUE(data_source_->IsStreaming());
224 }
225 }
226 }
227
228 void StopDataSource() {
229 if (loader_) {
230 InSequence s;
231 EXPECT_CALL(*loader_, Stop());
232 }
233
234 data_source_->Stop(media::NewExpectedClosure());
235 message_loop_->RunAllPending();
236 }
237
238 void InvokeStartCallback(
239 net::OldCompletionCallback* callback,
240 const base::Closure& network_callback,
241 WebFrame* frame) {
242 callback->RunWithParams(Tuple1<int>(error_));
243 delete callback;
244 // TODO(hclam): Save network_callback.
245 }
246
247 void InvokeReadCallback(int64 position, int size, uint8* buffer,
248 net::OldCompletionCallback* callback) {
249 if (error_ > 0)
250 memcpy(buffer, data_ + static_cast<int>(position), error_);
251 callback->RunWithParams(Tuple1<int>(error_));
252 delete callback;
253 }
254
255 void ReadDataSourceHit(int64 position, int size, int read_size) {
256 EXPECT_TRUE(loader_);
257
258 InSequence s;
259 // Expect the read is delegated to the resource loader.
260 EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
261 .WillOnce(DoAll(Assign(&error_, read_size),
262 Invoke(this,
263 &BufferedDataSourceTest::InvokeReadCallback)));
264
265 // The read has succeeded, so read callback will be called.
266 EXPECT_CALL(*this, ReadCallback(read_size));
267
268 data_source_->Read(
269 position, size, buffer_,
270 base::Bind(&BufferedDataSourceTest::ReadCallback,
271 base::Unretained(this)));
272 message_loop_->RunAllPending();
273
274 // Make sure data is correct.
275 EXPECT_EQ(0,
276 memcmp(buffer_, data_ + static_cast<int>(position), read_size));
277 }
278
279 void ReadDataSourceHang(int64 position, int size) {
280 EXPECT_TRUE(loader_);
281
282 // Expect a call to read, but the call never returns.
283 EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()));
284 data_source_->Read(
285 position, size, buffer_,
286 base::Bind(&BufferedDataSourceTest::ReadCallback,
287 base::Unretained(this)));
288 message_loop_->RunAllPending();
289
290 // Now expect the read to return after aborting the data source.
291 EXPECT_CALL(*this, ReadCallback(_));
292 EXPECT_CALL(*loader_, Stop());
293 data_source_->Abort();
294 message_loop_->RunAllPending();
295
296 // The loader has now been stopped. Set this to null so that when the
297 // DataSource is stopped, it does not expect a call to stop the loader.
298 loader_ = NULL;
299 }
300
301 void ReadDataSourceMiss(int64 position, int size, int start_error) {
302 EXPECT_TRUE(loader_);
303
304 // 1. Reply with a cache miss for the read.
305 {
306 InSequence s;
307 EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
308 .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS),
309 Invoke(this,
310 &BufferedDataSourceTest::InvokeReadCallback)));
311 EXPECT_CALL(*loader_, Stop());
312 }
313
314 // 2. Then the current loader will be stop and destroyed.
315 NiceMock<MockBufferedResourceLoader> *new_loader =
316 new NiceMock<MockBufferedResourceLoader>();
317 EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
318 .WillOnce(Return(new_loader));
319
320 // 3. Then the new loader will be started.
321 EXPECT_CALL(*new_loader, Start(NotNull(), _, NotNull()))
322 .WillOnce(DoAll(Assign(&error_, start_error),
323 Invoke(this,
324 &BufferedDataSourceTest::InvokeStartCallback)));
325
326 if (start_error == net::OK) {
327 EXPECT_CALL(*new_loader, range_supported())
328 .WillRepeatedly(Return(loader_->range_supported()));
329
330 // 4a. Then again a read request is made to the new loader.
331 EXPECT_CALL(*new_loader, Read(position, size, NotNull(), NotNull()))
332 .WillOnce(DoAll(Assign(&error_, size),
333 Invoke(this,
334 &BufferedDataSourceTest::InvokeReadCallback)));
335
336 EXPECT_CALL(*this, ReadCallback(size));
337 } else {
338 // 4b. The read callback is called with an error because Start() on the
339 // new loader returned an error.
340 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
341 }
342
343 data_source_->Read(
344 position, size, buffer_,
345 base::Bind(&BufferedDataSourceTest::ReadCallback,
346 base::Unretained(this)));
347 message_loop_->RunAllPending();
348
349 // Make sure data is correct.
350 if (start_error == net::OK)
351 EXPECT_EQ(0, memcmp(buffer_, data_ + static_cast<int>(position), size));
352
353 loader_ = new_loader;
354 }
355
356 void ReadDataSourceFailed(int64 position, int size, int error) {
357 EXPECT_TRUE(loader_);
358
359 // 1. Expect the read is delegated to the resource loader.
360 EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
361 .WillOnce(DoAll(Assign(&error_, error),
362 Invoke(this,
363 &BufferedDataSourceTest::InvokeReadCallback)));
364
365 // 2. Host will then receive an error.
366 EXPECT_CALL(*loader_, Stop());
367
368 // 3. The read has failed, so read callback will be called.
369 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
370
371 data_source_->Read(
372 position, size, buffer_,
373 base::Bind(&BufferedDataSourceTest::ReadCallback,
374 base::Unretained(this)));
375
376 message_loop_->RunAllPending();
377 }
378
379 BufferedResourceLoader* InvokeCacheMissCreateResourceLoader(int64 start,
380 int64 end) {
381 NiceMock<MockBufferedResourceLoader>* new_loader =
382 new NiceMock<MockBufferedResourceLoader>();
383
384 EXPECT_CALL(*new_loader, Start(NotNull(), _, NotNull()))
385 .WillOnce(DoAll(Assign(&error_, net::OK),
386 Invoke(this,
387 &BufferedDataSourceTest::InvokeStartCallback)));
388
389 EXPECT_CALL(*new_loader, range_supported())
390 .WillRepeatedly(Return(loader_->range_supported()));
391
392 int error = net::ERR_FAILED;
393 if (cache_miss_count_ < kMaxCacheMissesBeforeFailTest) {
394 cache_miss_count_++;
395 error = net::ERR_CACHE_MISS;
396 }
397
398 EXPECT_CALL(*new_loader, Read(start, _, NotNull(), NotNull()))
399 .WillOnce(DoAll(Assign(&error_, error),
400 Invoke(this,
401 &BufferedDataSourceTest::InvokeReadCallback)));
402
403 loader_ = new_loader;
404 return new_loader;
405 }
406
407 void ReadDataSourceAlwaysCacheMiss(int64 position, int size) {
408 cache_miss_count_ = 0;
409
410 EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
411 .WillRepeatedly(Invoke(
412 this,
413 &BufferedDataSourceTest::InvokeCacheMissCreateResourceLoader));
414
415 EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
416 .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS),
417 Invoke(this,
418 &BufferedDataSourceTest::InvokeReadCallback)));
419
420 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
421
422 data_source_->Read(
423 position, size, buffer_,
424 base::Bind(&BufferedDataSourceTest::ReadCallback,
425 base::Unretained(this)));
426
427 message_loop_->RunAllPending();
428
429 EXPECT_LT(cache_miss_count_, kMaxCacheMissesBeforeFailTest);
430 } 154 }
431 155
432 MOCK_METHOD1(ReadCallback, void(size_t size)); 156 MOCK_METHOD1(ReadCallback, void(size_t size));
433 157
434 scoped_refptr<NiceMock<MockBufferedResourceLoader> > loader_; 158 void ReadAt(int64 position) {
159 data_source_->Read(position, kDataSize, buffer_,
160 base::Bind(&BufferedDataSourceTest::ReadCallback,
161 base::Unretained(this)));
162 message_loop_->RunAllPending();
163 }
164
165 // Accessors for private variables on |data_source_|.
166 BufferedResourceLoader* loader() { return data_source_->loader_.get(); }
167 WebURLLoader* url_loader() { return loader()->url_loader_.get(); }
168
169 media::Preload preload() { return data_source_->preload_; }
170 BufferedResourceLoader::DeferStrategy defer_strategy() {
171 return loader()->defer_strategy_;
172 }
173 int data_source_bitrate() { return data_source_->bitrate_; }
174 int data_source_playback_rate() { return data_source_->playback_rate_; }
175 int loader_bitrate() { return loader()->bitrate_; }
176 int loader_playback_rate() { return loader()->playback_rate_; }
177
178
435 scoped_refptr<MockBufferedDataSource> data_source_; 179 scoped_refptr<MockBufferedDataSource> data_source_;
436 180
181 TestResponseGenerator response_generator_;
437 MockWebFrameClient client_; 182 MockWebFrameClient client_;
438 WebView* view_; 183 WebView* view_;
439 184
440 StrictMock<media::MockFilterHost> host_; 185 StrictMock<media::MockFilterHost> host_;
441 GURL gurl_;
442 MessageLoop* message_loop_; 186 MessageLoop* message_loop_;
443 187
444 int error_;
445 uint8 buffer_[1024];
446 uint8 data_[1024];
447
448 int cache_miss_count_;
449
450 private: 188 private:
189 // Used for calling BufferedDataSource::Read().
190 uint8 buffer_[kDataSize];
191
192 // Used for calling BufferedResourceLoader::didReceiveData().
193 char data_[kDataSize];
194
451 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest); 195 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
452 }; 196 };
453 197
454 TEST_F(BufferedDataSourceTest, InitializationSuccess) { 198 TEST_F(BufferedDataSourceTest, Range_Supported) {
455 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 199 Initialize(media::PIPELINE_OK);
456 StopDataSource(); 200
457 } 201 EXPECT_CALL(host_, SetLoaded(false));
458 202 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
459 TEST_F(BufferedDataSourceTest, InitiailizationFailed) { 203 EXPECT_CALL(host_, SetBufferedBytes(0));
460 InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, false, 0, NONE); 204 Respond(response_generator_.Generate206(0));
461 StopDataSource(); 205
462 } 206 EXPECT_TRUE(data_source_->loading());
463 207 Stop();
464 TEST_F(BufferedDataSourceTest, MissingContentLength) { 208 }
465 InitializeDataSource(kHttpUrl, net::OK, true, -1, LOADING); 209
466 StopDataSource(); 210 TEST_F(BufferedDataSourceTest, Range_NotFound) {
467 } 211 Initialize(media::PIPELINE_ERROR_NETWORK);
468 212
469 TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) { 213 // It'll try again.
470 InitializeDataSource(kHttpUrl, net::OK, false, 1024, LOADING); 214 //
471 StopDataSource(); 215 // TODO(scherkus): don't try again on errors http://crbug.com/105230
472 } 216 ExpectCreateResourceLoader();
473 217 Respond(response_generator_.Generate404());
474 // Test the case where we get a 206 response, but no Content-Range header. 218
475 TEST_F(BufferedDataSourceTest, MissingContentRange) { 219 // Now it's done and will fail.
476 InitializeDataSource(kHttpUrl, net::ERR_INVALID_RESPONSE, true, 1024, 220 Respond(response_generator_.Generate404());
477 LOADING); 221
478 StopDataSource(); 222 EXPECT_FALSE(data_source_->loading());
479 } 223 Stop();
480 224 }
481 TEST_F(BufferedDataSourceTest, 225
482 MissingContentLengthAndRangeRequestNotSupported) { 226 TEST_F(BufferedDataSourceTest, Range_NotSupported) {
483 InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING); 227 Initialize(media::PIPELINE_OK);
484 StopDataSource(); 228
485 } 229 // It'll try again.
486 230 //
487 TEST_F(BufferedDataSourceTest, ReadCacheHit) { 231 // TODO(scherkus): try to reuse existing connection http://crbug.com/105231
488 InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); 232 ExpectCreateResourceLoader();
489 233 Respond(response_generator_.Generate200());
490 // Performs read with cache hit. 234
491 ReadDataSourceHit(10, 10, 10); 235 // Now it'll succeed.
492 236 EXPECT_CALL(host_, SetLoaded(false));
493 // Performs read with cache hit but partially filled. 237 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
494 ReadDataSourceHit(20, 10, 5); 238 EXPECT_CALL(host_, SetBufferedBytes(0));
495 239 EXPECT_CALL(host_, SetStreaming(true));
496 StopDataSource(); 240 Respond(response_generator_.Generate200());
497 } 241
498 242 EXPECT_TRUE(data_source_->loading());
499 TEST_F(BufferedDataSourceTest, ReadCacheMiss) { 243 Stop();
500 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 244 }
501 ReadDataSourceMiss(1000, 10, net::OK); 245
502 ReadDataSourceMiss(20, 10, net::OK); 246 TEST_F(BufferedDataSourceTest, Range_MissingContentRange) {
503 StopDataSource(); 247 Initialize(media::PIPELINE_ERROR_NETWORK);
248
249 // It'll try again.
250 //
251 // TODO(scherkus): don't try again on errors http://crbug.com/105230
252 ExpectCreateResourceLoader();
253 Respond(response_generator_.Generate206(
254 0, TestResponseGenerator::kNoContentRange));
255
256 // Now it's done and will fail.
257 Respond(response_generator_.Generate206(
258 0, TestResponseGenerator::kNoContentRange));
259
260 EXPECT_FALSE(data_source_->loading());
261 Stop();
262 }
263
264 TEST_F(BufferedDataSourceTest, Range_MissingContentLength) {
265 Initialize(media::PIPELINE_OK);
266
267 // It'll manage without a Content-Length response.
268 EXPECT_CALL(host_, SetLoaded(false));
269 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
270 EXPECT_CALL(host_, SetBufferedBytes(0));
271 Respond(response_generator_.Generate206(
272 0, TestResponseGenerator::kNoContentLength));
273
274 EXPECT_TRUE(data_source_->loading());
275 Stop();
276 }
277
278 TEST_F(BufferedDataSourceTest, Range_WrongContentRange) {
279 Initialize(media::PIPELINE_ERROR_NETWORK);
280
281 // It'll try again.
282 //
283 // TODO(scherkus): don't try again on errors http://crbug.com/105230
284 ExpectCreateResourceLoader();
285 Respond(response_generator_.Generate206(1337));
286
287 // Now it's done and will fail.
288 Respond(response_generator_.Generate206(1337));
289
290 EXPECT_FALSE(data_source_->loading());
291 Stop();
504 } 292 }
505 293
506 // Test the case where the initial response from the server indicates that 294 // Test the case where the initial response from the server indicates that
507 // Range requests are supported, but a later request prove otherwise. 295 // Range requests are supported, but a later request prove otherwise.
508 TEST_F(BufferedDataSourceTest, ServerLiesAboutRangeSupport) { 296 TEST_F(BufferedDataSourceTest, Range_ServerLied) {
509 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 297 InitializeWith206Response();
510 ReadDataSourceHit(10, 10, 10); 298
511 ReadDataSourceMiss(1000, 10, net::ERR_INVALID_RESPONSE); 299 // Read causing a new request to be made -- we'll expect it to error.
512 StopDataSource(); 300 ExpectCreateResourceLoader();
513 } 301 ReadAt(kFarReadPosition);
514 302
515 TEST_F(BufferedDataSourceTest, ReadHang) { 303 // Return a 200 in response to a range request.
516 InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); 304 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
517 ReadDataSourceHang(10, 10); 305 Respond(response_generator_.Generate200());
518 StopDataSource(); 306
519 } 307 EXPECT_FALSE(data_source_->loading());
520 308 Stop();
521 TEST_F(BufferedDataSourceTest, ReadFailed) { 309 }
522 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 310
523 ReadDataSourceHit(10, 10, 10); 311 TEST_F(BufferedDataSourceTest, Range_AbortWhileReading) {
524 ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET); 312 InitializeWith206Response();
525 StopDataSource(); 313
526 } 314 // Make sure there's a pending read -- we'll expect it to error.
527 315 ReadAt(0);
528 // Helper that sets |*value| to true. Useful for binding into a Closure. 316
317 // Abort!!!
318 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
319 data_source_->Abort();
320 message_loop_->RunAllPending();
321
322 EXPECT_FALSE(data_source_->loading());
323 Stop();
324 }
325
326 TEST_F(BufferedDataSourceTest, Range_TooManyRetries) {
327 InitializeWith206Response();
328
329 // Make sure there's a pending read -- we'll expect it to error.
330 ReadAt(0);
331
332 // It'll try three times.
333 ExpectCreateResourceLoader();
334 FinishLoading();
335 Respond(response_generator_.Generate206(0));
336
337 ExpectCreateResourceLoader();
338 FinishLoading();
339 Respond(response_generator_.Generate206(0));
340
341 ExpectCreateResourceLoader();
342 FinishLoading();
343 Respond(response_generator_.Generate206(0));
344
345 // It'll error after this.
346 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
347 FinishLoading();
348
349 EXPECT_FALSE(data_source_->loading());
350 Stop();
351 }
352
529 static void SetTrue(bool* value) { 353 static void SetTrue(bool* value) {
530 *value = true; 354 *value = true;
531 } 355 }
532 356
533 // This test makes sure that Stop() does not require a task to run on 357 // This test makes sure that Stop() does not require a task to run on
534 // |message_loop_| before it calls its callback. This prevents accidental 358 // |message_loop_| before it calls its callback. This prevents accidental
535 // introduction of a pipeline teardown deadlock. The pipeline owner blocks 359 // introduction of a pipeline teardown deadlock. The pipeline owner blocks
536 // the render message loop while waiting for Stop() to complete. Since this 360 // the render message loop while waiting for Stop() to complete. Since this
537 // object runs on the render message loop, Stop() will not complete if it 361 // object runs on the render message loop, Stop() will not complete if it
538 // requires a task to run on the the message loop that is being blocked. 362 // requires a task to run on the the message loop that is being blocked.
539 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) { 363 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
540 InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); 364 InitializeWith206Response();
541 365
542 // Stop() the data source, using a callback that lets us verify that it was 366 // Stop() the data source, using a callback that lets us verify that it was
543 // called before Stop() returns. This is to make sure that the callback does 367 // called before Stop() returns. This is to make sure that the callback does
544 // not require |message_loop_| to execute tasks before being called. 368 // not require |message_loop_| to execute tasks before being called.
545 bool stop_done_called = false; 369 bool stop_done_called = false;
370 EXPECT_TRUE(data_source_->loading());
546 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called)); 371 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called));
547 372
548 // Verify that the callback was called inside the Stop() call. 373 // Verify that the callback was called inside the Stop() call.
549 EXPECT_TRUE(stop_done_called); 374 EXPECT_TRUE(stop_done_called);
550
551 message_loop_->RunAllPending(); 375 message_loop_->RunAllPending();
552 } 376 }
553 377
554 TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) { 378 TEST_F(BufferedDataSourceTest, DefaultValues) {
555 InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); 379 InitializeWith206Response();
556
557 // Setup a way to verify that Read() is not called on the loader.
558 // We are doing this to make sure that the ReadTask() is still on
559 // the message loop queue when Abort() is called.
560 bool read_called = false;
561 ON_CALL(*loader_, Read(_, _, _ , _))
562 .WillByDefault(DoAll(Assign(&read_called, true),
563 DeleteArg<3>()));
564
565 // Initiate a Read() on the data source, but don't allow the
566 // message loop to run.
567 data_source_->Read(
568 0, 10, buffer_,
569 base::Bind(&BufferedDataSourceTest::ReadCallback,
570 base::Unretained(static_cast<BufferedDataSourceTest*>(this))));
571
572 // Call Abort() with the read pending.
573 EXPECT_CALL(*this, ReadCallback(-1));
574 EXPECT_CALL(*loader_, Stop());
575 data_source_->Abort();
576
577 // Verify that Read()'s after the Abort() issue callback with an error.
578 EXPECT_CALL(*this, ReadCallback(-1));
579 data_source_->Read(
580 0, 10, buffer_,
581 base::Bind(&BufferedDataSourceTest::ReadCallback,
582 base::Unretained(static_cast<BufferedDataSourceTest*>(this))));
583
584 // Stop() the data source like normal.
585 data_source_->Stop(media::NewExpectedClosure());
586
587 // Allow cleanup task to run.
588 message_loop_->RunAllPending();
589
590 // Verify that Read() was not called on the loader.
591 EXPECT_FALSE(read_called);
592 }
593
594 // Test that we only allow a limited number of cache misses for a
595 // single Read() request.
596 TEST_F(BufferedDataSourceTest, BoundedCacheMisses) {
597 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
598
599 ReadDataSourceAlwaysCacheMiss(0, 10);
600
601 StopDataSource();
602 }
603
604 // TODO(scherkus): de-dupe from buffered_resource_loader_unittest.cc
605 ACTION_P(RequestCanceled, loader) {
606 WebURLError error;
607 error.reason = net::ERR_ABORTED;
608 error.domain = WebString::fromUTF8(net::kErrorDomain);
609 loader->didFail(NULL, error);
610 }
611
612 // A more realistic BufferedDataSource that uses BufferedResourceLoader instead
613 // of a mocked version but injects a MockWebURLLoader.
614 //
615 // TODO(scherkus): re-write these tests to use this class then drop the "2"
616 // suffix.
617 class MockBufferedDataSource2 : public BufferedDataSource {
618 public:
619 MockBufferedDataSource2(MessageLoop* message_loop, WebFrame* frame)
620 : BufferedDataSource(message_loop, frame, new media::MediaLog()),
621 url_loader_(NULL) {
622 }
623
624 virtual base::TimeDelta GetTimeoutMilliseconds() {
625 return base::TimeDelta::FromMilliseconds(
626 TestTimeouts::tiny_timeout_ms());
627 }
628
629 virtual BufferedResourceLoader* CreateResourceLoader(int64 first_position,
630 int64 last_position) {
631 loader_ = BufferedDataSource::CreateResourceLoader(first_position,
632 last_position);
633
634 url_loader_ = new NiceMock<MockWebURLLoader>();
635 ON_CALL(*url_loader_, cancel())
636 .WillByDefault(RequestCanceled(loader_));
637
638 loader_->SetURLLoaderForTest(url_loader_);
639 return loader_;
640 }
641
642 const scoped_refptr<BufferedResourceLoader>& loader() { return loader_; }
643 NiceMock<MockWebURLLoader>* url_loader() { return url_loader_; }
644
645 private:
646 scoped_refptr<BufferedResourceLoader> loader_;
647 NiceMock<MockWebURLLoader>* url_loader_;
648
649 DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource2);
650 };
651
652 class BufferedDataSourceTest2 : public testing::Test {
653 public:
654 BufferedDataSourceTest2()
655 : view_(WebView::create(NULL)),
656 message_loop_(MessageLoop::current()) {
657 view_->initializeMainFrame(&client_);
658 }
659
660 virtual ~BufferedDataSourceTest2() {
661 view_->close();
662 }
663
664 void InitializeDataSource(const char* url) {
665 gurl_ = GURL(url);
666
667 data_source_ = new MockBufferedDataSource2(message_loop_,
668 view_->mainFrame());
669 data_source_->set_host(&host_);
670 data_source_->Initialize(url,
671 media::NewExpectedStatusCB(media::PIPELINE_OK));
672 message_loop_->RunAllPending();
673
674 // Simulate 206 response for a 5,000,000 byte length file.
675 WebURLResponse response(gurl_);
676 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
677 WebString::fromUTF8("bytes"));
678 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
679 WebString::fromUTF8("bytes 0-4999999/5000000"));
680 response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
681 WebString::fromUTF8("5000000"));
682 response.setExpectedContentLength(5000000);
683 response.setHTTPStatusCode(206);
684
685 // We should receive corresponding information about the media resource.
686 EXPECT_CALL(host_, SetLoaded(false));
687 EXPECT_CALL(host_, SetTotalBytes(5000000));
688 EXPECT_CALL(host_, SetBufferedBytes(0));
689
690 data_source_->loader()->didReceiveResponse(data_source_->url_loader(),
691 response);
692
693 message_loop_->RunAllPending();
694 }
695
696 void StopDataSource() {
697 data_source_->Stop(media::NewExpectedClosure());
698 message_loop_->RunAllPending();
699 }
700
701 MOCK_METHOD1(ReadCallback, void(size_t size));
702 media::DataSource::ReadCallback NewReadCallback(size_t size) {
703 EXPECT_CALL(*this, ReadCallback(size));
704 return base::Bind(&BufferedDataSourceTest2::ReadCallback,
705 base::Unretained(this));
706 }
707
708 // Accessors for private variables on |data_source_|.
709 media::Preload preload() { return data_source_->preload_; }
710 BufferedResourceLoader::DeferStrategy defer_strategy() {
711 return data_source_->loader()->defer_strategy_;
712 }
713 int data_source_bitrate() { return data_source_->bitrate_; }
714 int data_source_playback_rate() { return data_source_->playback_rate_; }
715 int loader_bitrate() { return data_source_->loader()->bitrate_; }
716 int loader_playback_rate() { return data_source_->loader()->playback_rate_; }
717
718 scoped_refptr<MockBufferedDataSource2> data_source_;
719
720 GURL gurl_;
721 MockWebFrameClient client_;
722 WebView* view_;
723
724 StrictMock<media::MockFilterHost> host_;
725 MessageLoop* message_loop_;
726
727 private:
728 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest2);
729 };
730
731 TEST_F(BufferedDataSourceTest2, Default) {
732 InitializeDataSource("http://localhost/foo.webm");
733 380
734 // Ensure we have sane values for default loading scenario. 381 // Ensure we have sane values for default loading scenario.
735 EXPECT_EQ(media::AUTO, preload()); 382 EXPECT_EQ(media::AUTO, preload());
736 EXPECT_EQ(BufferedResourceLoader::kThresholdDefer, defer_strategy()); 383 EXPECT_EQ(BufferedResourceLoader::kThresholdDefer, defer_strategy());
737 384
738 EXPECT_EQ(0, data_source_bitrate()); 385 EXPECT_EQ(0, data_source_bitrate());
739 EXPECT_EQ(0.0f, data_source_playback_rate()); 386 EXPECT_EQ(0.0f, data_source_playback_rate());
740 EXPECT_EQ(0, loader_bitrate()); 387 EXPECT_EQ(0, loader_bitrate());
741 EXPECT_EQ(0.0f, loader_playback_rate()); 388 EXPECT_EQ(0.0f, loader_playback_rate());
742 389
743 StopDataSource(); 390 EXPECT_TRUE(data_source_->loading());
391 Stop();
744 } 392 }
745 393
746 TEST_F(BufferedDataSourceTest2, SetBitrate) { 394 TEST_F(BufferedDataSourceTest, SetBitrate) {
747 InitializeDataSource("http://localhost/foo.webm"); 395 InitializeWith206Response();
748 396
749 data_source_->SetBitrate(1234); 397 data_source_->SetBitrate(1234);
750 message_loop_->RunAllPending(); 398 message_loop_->RunAllPending();
751 EXPECT_EQ(1234, data_source_bitrate()); 399 EXPECT_EQ(1234, data_source_bitrate());
752 EXPECT_EQ(1234, loader_bitrate()); 400 EXPECT_EQ(1234, loader_bitrate());
753 401
754 // Read so far ahead to cause the loader to get recreated. 402 // Read so far ahead to cause the loader to get recreated.
755 BufferedResourceLoader* old_loader = data_source_->loader(); 403 BufferedResourceLoader* old_loader = loader();
756 404 ExpectCreateResourceLoader();
757 uint8 buffer[1024]; 405 ReadAt(kFarReadPosition);
758 data_source_->Read(4000000, 1024, buffer, 406 Respond(response_generator_.Generate206(kFarReadPosition));
759 NewReadCallback(media::DataSource::kReadError));
760 message_loop_->RunAllPending();
761 407
762 // Verify loader changed but still has same bitrate. 408 // Verify loader changed but still has same bitrate.
763 EXPECT_NE(old_loader, data_source_->loader().get()); 409 EXPECT_NE(old_loader, loader());
764 EXPECT_EQ(1234, loader_bitrate()); 410 EXPECT_EQ(1234, loader_bitrate());
765 411
766 StopDataSource(); 412 EXPECT_TRUE(data_source_->loading());
413 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
414 Stop();
767 } 415 }
768 416
769 TEST_F(BufferedDataSourceTest2, SetPlaybackRate) { 417 TEST_F(BufferedDataSourceTest, SetPlaybackRate) {
770 InitializeDataSource("http://localhost/foo.webm"); 418 InitializeWith206Response();
771 419
772 data_source_->SetPlaybackRate(2.0f); 420 data_source_->SetPlaybackRate(2.0f);
773 message_loop_->RunAllPending(); 421 message_loop_->RunAllPending();
774 EXPECT_EQ(2.0f, data_source_playback_rate()); 422 EXPECT_EQ(2.0f, data_source_playback_rate());
775 EXPECT_EQ(2.0f, loader_playback_rate()); 423 EXPECT_EQ(2.0f, loader_playback_rate());
776 424
777 // Read so far ahead to cause the loader to get recreated. 425 // Read so far ahead to cause the loader to get recreated.
778 BufferedResourceLoader* old_loader = data_source_->loader(); 426 BufferedResourceLoader* old_loader = loader();
427 ExpectCreateResourceLoader();
428 ReadAt(kFarReadPosition);
429 Respond(response_generator_.Generate206(kFarReadPosition));
779 430
780 uint8 buffer[1024]; 431 // Verify loader changed but still has same playback rate.
781 data_source_->Read(4000000, 1024, buffer, 432 EXPECT_NE(old_loader, loader());
782 NewReadCallback(media::DataSource::kReadError));
783 message_loop_->RunAllPending();
784 433
785 // Verify loader changed but still has same bitrate. 434 EXPECT_TRUE(data_source_->loading());
786 EXPECT_NE(old_loader, data_source_->loader().get()); 435 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
787 EXPECT_EQ(2.0f, loader_playback_rate()); 436 Stop();
437 }
788 438
789 StopDataSource(); 439 TEST_F(BufferedDataSourceTest, Read) {
440 InitializeWith206Response();
441
442 ReadAt(0);
443
444 // When the read completes we'll update our network status.
445 EXPECT_CALL(host_, SetBufferedBytes(kDataSize));
446 EXPECT_CALL(host_, SetNetworkActivity(true));
447 EXPECT_CALL(*this, ReadCallback(kDataSize));
448 FinishRead();
449
450 // During teardown we'll also report our final network status.
451 EXPECT_CALL(host_, SetBufferedBytes(kDataSize));
452 EXPECT_CALL(host_, SetNetworkActivity(false));
453
454 EXPECT_TRUE(data_source_->loading());
455 Stop();
790 } 456 }
791 457
792 } // namespace webkit_media 458 } // namespace webkit_media
OLDNEW
« no previous file with comments | « webkit/media/buffered_data_source.h ('k') | webkit/media/buffered_resource_loader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698