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

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: comments Created 9 years, 1 month 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
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 : 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 83
107 class BufferedDataSourceTest : public testing::Test { 84 class BufferedDataSourceTest : public testing::Test {
108 public: 85 public:
109 BufferedDataSourceTest() 86 BufferedDataSourceTest()
110 : view_(WebView::create(NULL)) { 87 : response_generator_(GURL("http://localhost/foo.webm"), kFileSize),
88 view_(WebView::create(NULL)),
89 message_loop_(MessageLoop::current()) {
111 view_->initializeMainFrame(&client_); 90 view_->initializeMainFrame(&client_);
112 message_loop_ = MessageLoop::current(); 91
113 92 data_source_ = new MockBufferedDataSource(message_loop_,
114 for (size_t i = 0; i < sizeof(data_); ++i) { 93 view_->mainFrame());
115 data_[i] = i; 94 data_source_->set_host(&host_);
116 }
117 } 95 }
118 96
119 virtual ~BufferedDataSourceTest() { 97 virtual ~BufferedDataSourceTest() {
120 view_->close(); 98 view_->close();
121 } 99 }
122 100
123 void ExpectCreateAndStartResourceLoader(int start_error) { 101 void Initialize(media::PipelineStatus expected) {
102 data_source_->Initialize(response_generator_.gurl().spec(),
103 media::NewExpectedStatusCB(expected));
104 message_loop_->RunAllPending();
105 }
106
107 // Helper to initialize tests with a valid 206 response.
108 void InitializeWith206Response() {
109 ExpectCreateResourceLoader();
110 Initialize(media::PIPELINE_OK);
111
112 EXPECT_CALL(host_, SetLoaded(false));
113 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
114 EXPECT_CALL(host_, SetBufferedBytes(0));
115 Respond(response_generator_.Generate206(0));
116 }
117
118 // Stops all active loaders and shuts down the data source.
119 //
120 // This typically happens when the page is closed and for our purposes is
121 // appropriate to do when tearing down a test.
122 void Stop() {
123 CHECK(data_source_->loading())
124 << "You don't need to stop if there is nothing loading";
125
126 loader()->didFail(url_loader(), response_generator_.GenerateError());
127 message_loop_->RunAllPending();
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( 154 }
145 new NiceMock<MockBufferedResourceLoader>()); 155
146 156 MOCK_METHOD1(ReadCallback, void(size_t size));
147 // Creates the mock loader to be injected. 157
148 loader_ = first_loader; 158 void ReadAt(int64 position) {
149 159 EXPECT_CALL(*this, ReadCallback(kDataSize));
150 bool initialized_ok = (error == net::OK); 160 data_source_->Read(position, kDataSize, buffer_,
151 bool loaded = networkState == LOADED; 161 base::Bind(&BufferedDataSourceTest::ReadCallback,
152 { 162 base::Unretained(this)));
153 InSequence s; 163 message_loop_->RunAllPending();
154 ExpectCreateAndStartResourceLoader(error); 164 }
155 165
156 // In the case of an invalid partial response we expect a second loader 166 void ReadAtWithError(int64 position) {
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)); 167 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
370 168 data_source_->Read(position, kDataSize, buffer_,
371 data_source_->Read( 169 base::Bind(&BufferedDataSourceTest::ReadCallback,
372 position, size, buffer_, 170 base::Unretained(this)));
373 base::Bind(&BufferedDataSourceTest::ReadCallback, 171 message_loop_->RunAllPending();
374 base::Unretained(this))); 172 }
375 173
376 message_loop_->RunAllPending(); 174 // Accessors for private variables on |data_source_|.
377 } 175 BufferedResourceLoader* loader() { return data_source_->loader_.get(); }
378 176 WebURLLoader* url_loader() { return loader()->url_loader_.get(); }
379 BufferedResourceLoader* InvokeCacheMissCreateResourceLoader(int64 start, 177
380 int64 end) { 178 media::Preload preload() { return data_source_->preload_; }
381 NiceMock<MockBufferedResourceLoader>* new_loader = 179 BufferedResourceLoader::DeferStrategy defer_strategy() {
382 new NiceMock<MockBufferedResourceLoader>(); 180 return loader()->defer_strategy_;
383 181 }
384 EXPECT_CALL(*new_loader, Start(NotNull(), _, NotNull())) 182 int data_source_bitrate() { return data_source_->bitrate_; }
385 .WillOnce(DoAll(Assign(&error_, net::OK), 183 int data_source_playback_rate() { return data_source_->playback_rate_; }
386 Invoke(this, 184 int loader_bitrate() { return loader()->bitrate_; }
387 &BufferedDataSourceTest::InvokeStartCallback))); 185 int loader_playback_rate() { return loader()->playback_rate_; }
388 186
389 EXPECT_CALL(*new_loader, range_supported()) 187
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 }
431
432 MOCK_METHOD1(ReadCallback, void(size_t size));
433
434 scoped_refptr<NiceMock<MockBufferedResourceLoader> > loader_;
435 scoped_refptr<MockBufferedDataSource> data_source_; 188 scoped_refptr<MockBufferedDataSource> data_source_;
436 189
190 TestResponseGenerator response_generator_;
437 MockWebFrameClient client_; 191 MockWebFrameClient client_;
438 WebView* view_; 192 WebView* view_;
439 193
440 StrictMock<media::MockFilterHost> host_; 194 StrictMock<media::MockFilterHost> host_;
441 GURL gurl_;
442 MessageLoop* message_loop_; 195 MessageLoop* message_loop_;
443 196
444 int error_;
445 uint8 buffer_[1024];
446 uint8 data_[1024];
447
448 int cache_miss_count_;
449
450 private: 197 private:
198 static const size_t kDataSize = 1024;
199
200 // Used for calling BufferedDataSource::Read().
201 uint8 buffer_[kDataSize];
202
203 // Used for calling BufferedResourceLoader::didReceiveData().
204 char data_[kDataSize];
205
451 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest); 206 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
452 }; 207 };
453 208
454 TEST_F(BufferedDataSourceTest, InitializationSuccess) { 209 TEST_F(BufferedDataSourceTest, Range_Supported) {
455 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 210 ExpectCreateResourceLoader();
456 StopDataSource(); 211 Initialize(media::PIPELINE_OK);
457 } 212
458 213 EXPECT_CALL(host_, SetLoaded(false));
459 TEST_F(BufferedDataSourceTest, InitiailizationFailed) { 214 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
460 InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, false, 0, NONE); 215 EXPECT_CALL(host_, SetBufferedBytes(0));
461 StopDataSource(); 216 Respond(response_generator_.Generate206(0));
462 } 217 Stop();
463 218 }
464 TEST_F(BufferedDataSourceTest, MissingContentLength) { 219
465 InitializeDataSource(kHttpUrl, net::OK, true, -1, LOADING); 220 TEST_F(BufferedDataSourceTest, Range_NotFound) {
466 StopDataSource(); 221 ExpectCreateResourceLoader();
467 } 222 Initialize(media::PIPELINE_ERROR_NETWORK);
468 223
469 TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) { 224 // It'll try again.
470 InitializeDataSource(kHttpUrl, net::OK, false, 1024, LOADING); 225 //
471 StopDataSource(); 226 // TODO(scherkus): don't try again on errors http://crbug.com/105230
472 } 227 ExpectCreateResourceLoader();
473 228 Respond(response_generator_.Generate404());
474 // Test the case where we get a 206 response, but no Content-Range header. 229
475 TEST_F(BufferedDataSourceTest, MissingContentRange) { 230 // Now it's done and will fail.
476 InitializeDataSource(kHttpUrl, net::ERR_INVALID_RESPONSE, true, 1024, 231 Respond(response_generator_.Generate404());
477 LOADING); 232 }
478 StopDataSource(); 233
479 } 234 TEST_F(BufferedDataSourceTest, Range_NotSupported) {
480 235 ExpectCreateResourceLoader();
481 TEST_F(BufferedDataSourceTest, 236 Initialize(media::PIPELINE_OK);
482 MissingContentLengthAndRangeRequestNotSupported) { 237
483 InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING); 238 // It'll try again.
484 StopDataSource(); 239 //
485 } 240 // TODO(scherkus): try to reuse existing connection http://crbug.com/105231
486 241 ExpectCreateResourceLoader();
487 TEST_F(BufferedDataSourceTest, ReadCacheHit) { 242 Respond(response_generator_.Generate200());
488 InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); 243
489 244 // Now it'll succeed.
490 // Performs read with cache hit. 245 EXPECT_CALL(host_, SetLoaded(false));
491 ReadDataSourceHit(10, 10, 10); 246 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
492 247 EXPECT_CALL(host_, SetBufferedBytes(0));
493 // Performs read with cache hit but partially filled. 248 EXPECT_CALL(host_, SetStreaming(true));
494 ReadDataSourceHit(20, 10, 5); 249 Respond(response_generator_.Generate200());
495 250 Stop();
496 StopDataSource(); 251 }
497 } 252
498 253 TEST_F(BufferedDataSourceTest, Range_MissingContentRange) {
499 TEST_F(BufferedDataSourceTest, ReadCacheMiss) { 254 ExpectCreateResourceLoader();
500 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 255 Initialize(media::PIPELINE_ERROR_NETWORK);
501 ReadDataSourceMiss(1000, 10, net::OK); 256
502 ReadDataSourceMiss(20, 10, net::OK); 257 // It'll try again.
503 StopDataSource(); 258 //
259 // TODO(scherkus): don't try again on errors http://crbug.com/105230
260 ExpectCreateResourceLoader();
261 Respond(response_generator_.Generate206(
262 0, TestResponseGenerator::kNoContentRange));
263
264 // Now it's done and will fail.
265 Respond(response_generator_.Generate206(
266 0, TestResponseGenerator::kNoContentRange));
267 }
268
269 TEST_F(BufferedDataSourceTest, Range_MissingContentLength) {
270 ExpectCreateResourceLoader();
271 Initialize(media::PIPELINE_OK);
272
273 // It'll manage without a Content-Length response.
274 EXPECT_CALL(host_, SetLoaded(false));
275 EXPECT_CALL(host_, SetTotalBytes(response_generator_.content_length()));
276 EXPECT_CALL(host_, SetBufferedBytes(0));
277 Respond(response_generator_.Generate206(
278 0, TestResponseGenerator::kNoContentLength));
279 Stop();
280 }
281
282 TEST_F(BufferedDataSourceTest, Range_WrongContentRange) {
283 ExpectCreateResourceLoader();
284 Initialize(media::PIPELINE_ERROR_NETWORK);
285
286 // It'll try again.
287 //
288 // TODO(scherkus): don't try again on errors http://crbug.com/105230
289 ExpectCreateResourceLoader();
290 Respond(response_generator_.Generate206(1337));
291
292 // Now it's done and will fail.
293 Respond(response_generator_.Generate206(1337));
504 } 294 }
505 295
506 // Test the case where the initial response from the server indicates that 296 // Test the case where the initial response from the server indicates that
507 // Range requests are supported, but a later request prove otherwise. 297 // Range requests are supported, but a later request prove otherwise.
508 TEST_F(BufferedDataSourceTest, ServerLiesAboutRangeSupport) { 298 TEST_F(BufferedDataSourceTest, Range_ServerLied) {
509 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 299 InitializeWith206Response();
510 ReadDataSourceHit(10, 10, 10); 300
511 ReadDataSourceMiss(1000, 10, net::ERR_INVALID_RESPONSE); 301 // Read causing a new request to be made -- we'll expect it to error.
512 StopDataSource(); 302 ExpectCreateResourceLoader();
513 } 303 ReadAtWithError(kFarReadPosition);
514 304
515 TEST_F(BufferedDataSourceTest, ReadHang) { 305 // Return a 200 in response to a range request.
516 InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); 306 Respond(response_generator_.Generate200());
517 ReadDataSourceHang(10, 10); 307 }
518 StopDataSource(); 308
519 } 309 TEST_F(BufferedDataSourceTest, Range_AbortWhileReading) {
520 310 InitializeWith206Response();
521 TEST_F(BufferedDataSourceTest, ReadFailed) { 311
522 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); 312 // Make sure there's a pending read -- we'll expect it to error.
523 ReadDataSourceHit(10, 10, 10); 313 ReadAtWithError(0);
524 ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET); 314
525 StopDataSource(); 315 // Abort!!!
526 } 316 data_source_->Abort();
527 317 message_loop_->RunAllPending();
528 // Helper that sets |*value| to true. Useful for binding into a Closure. 318 }
319
320 TEST_F(BufferedDataSourceTest, Range_TooManyRetries) {
321 InitializeWith206Response();
322
323 // Make sure there's a pending read -- we'll expect it to error.
324 ReadAtWithError(0);
325
326 // It'll try three times.
327 ExpectCreateResourceLoader();
328 FinishLoading();
329 Respond(response_generator_.Generate206(0));
330
331 ExpectCreateResourceLoader();
332 FinishLoading();
333 Respond(response_generator_.Generate206(0));
334
335 ExpectCreateResourceLoader();
336 FinishLoading();
337 Respond(response_generator_.Generate206(0));
338
339 // It'll error after this.
340 FinishLoading();
341 }
342
529 static void SetTrue(bool* value) { 343 static void SetTrue(bool* value) {
530 *value = true; 344 *value = true;
531 } 345 }
532 346
533 // This test makes sure that Stop() does not require a task to run on 347 // 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 348 // |message_loop_| before it calls its callback. This prevents accidental
535 // introduction of a pipeline teardown deadlock. The pipeline owner blocks 349 // introduction of a pipeline teardown deadlock. The pipeline owner blocks
536 // the render message loop while waiting for Stop() to complete. Since this 350 // 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 351 // 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. 352 // requires a task to run on the the message loop that is being blocked.
539 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) { 353 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
540 InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); 354 InitializeWith206Response();
541 355
542 // Stop() the data source, using a callback that lets us verify that it was 356 // 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 357 // called before Stop() returns. This is to make sure that the callback does
544 // not require |message_loop_| to execute tasks before being called. 358 // not require |message_loop_| to execute tasks before being called.
545 bool stop_done_called = false; 359 bool stop_done_called = false;
546 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called)); 360 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called));
547 361
548 // Verify that the callback was called inside the Stop() call. 362 // Verify that the callback was called inside the Stop() call.
549 EXPECT_TRUE(stop_done_called); 363 EXPECT_TRUE(stop_done_called);
550
551 message_loop_->RunAllPending(); 364 message_loop_->RunAllPending();
552 } 365 }
553 366
554 TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) { 367 TEST_F(BufferedDataSourceTest, DefaultValues) {
555 InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); 368 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 369
734 // Ensure we have sane values for default loading scenario. 370 // Ensure we have sane values for default loading scenario.
735 EXPECT_EQ(media::AUTO, preload()); 371 EXPECT_EQ(media::AUTO, preload());
736 EXPECT_EQ(BufferedResourceLoader::kThresholdDefer, defer_strategy()); 372 EXPECT_EQ(BufferedResourceLoader::kThresholdDefer, defer_strategy());
737 373
738 EXPECT_EQ(0, data_source_bitrate()); 374 EXPECT_EQ(0, data_source_bitrate());
739 EXPECT_EQ(0.0f, data_source_playback_rate()); 375 EXPECT_EQ(0.0f, data_source_playback_rate());
740 EXPECT_EQ(0, loader_bitrate()); 376 EXPECT_EQ(0, loader_bitrate());
741 EXPECT_EQ(0.0f, loader_playback_rate()); 377 EXPECT_EQ(0.0f, loader_playback_rate());
742 378 Stop();
743 StopDataSource();
744 } 379 }
745 380
746 TEST_F(BufferedDataSourceTest2, SetBitrate) { 381 TEST_F(BufferedDataSourceTest, SetBitrate) {
747 InitializeDataSource("http://localhost/foo.webm"); 382 InitializeWith206Response();
748 383
749 data_source_->SetBitrate(1234); 384 data_source_->SetBitrate(1234);
750 message_loop_->RunAllPending(); 385 message_loop_->RunAllPending();
751 EXPECT_EQ(1234, data_source_bitrate()); 386 EXPECT_EQ(1234, data_source_bitrate());
752 EXPECT_EQ(1234, loader_bitrate()); 387 EXPECT_EQ(1234, loader_bitrate());
753 388
754 // Read so far ahead to cause the loader to get recreated. 389 // Read so far ahead to cause the loader to get recreated.
755 BufferedResourceLoader* old_loader = data_source_->loader(); 390 BufferedResourceLoader* old_loader = loader();
756 391 ExpectCreateResourceLoader();
757 uint8 buffer[1024]; 392 ReadAtWithError(kFarReadPosition);
758 data_source_->Read(4000000, 1024, buffer, 393 Respond(response_generator_.Generate206(kFarReadPosition));
759 NewReadCallback(media::DataSource::kReadError));
760 message_loop_->RunAllPending();
761 394
762 // Verify loader changed but still has same bitrate. 395 // Verify loader changed but still has same bitrate.
763 EXPECT_NE(old_loader, data_source_->loader().get()); 396 EXPECT_NE(old_loader, loader());
764 EXPECT_EQ(1234, loader_bitrate()); 397 EXPECT_EQ(1234, loader_bitrate());
765 398 Stop();
766 StopDataSource();
767 } 399 }
768 400
769 TEST_F(BufferedDataSourceTest2, SetPlaybackRate) { 401 TEST_F(BufferedDataSourceTest, SetPlaybackRate) {
770 InitializeDataSource("http://localhost/foo.webm"); 402 InitializeWith206Response();
771 403
772 data_source_->SetPlaybackRate(2.0f); 404 data_source_->SetPlaybackRate(2.0f);
773 message_loop_->RunAllPending(); 405 message_loop_->RunAllPending();
774 EXPECT_EQ(2.0f, data_source_playback_rate()); 406 EXPECT_EQ(2.0f, data_source_playback_rate());
775 EXPECT_EQ(2.0f, loader_playback_rate()); 407 EXPECT_EQ(2.0f, loader_playback_rate());
776 408
777 // Read so far ahead to cause the loader to get recreated. 409 // Read so far ahead to cause the loader to get recreated.
778 BufferedResourceLoader* old_loader = data_source_->loader(); 410 BufferedResourceLoader* old_loader = loader();
779 411 ExpectCreateResourceLoader();
780 uint8 buffer[1024]; 412 ReadAtWithError(kFarReadPosition);
781 data_source_->Read(4000000, 1024, buffer, 413 Respond(response_generator_.Generate206(kFarReadPosition));
782 NewReadCallback(media::DataSource::kReadError));
783 message_loop_->RunAllPending();
784 414
785 // Verify loader changed but still has same bitrate. 415 // Verify loader changed but still has same bitrate.
786 EXPECT_NE(old_loader, data_source_->loader().get()); 416 EXPECT_NE(old_loader, loader());
787 EXPECT_EQ(2.0f, loader_playback_rate()); 417 Stop();
418 }
788 419
789 StopDataSource(); 420 TEST_F(BufferedDataSourceTest, Read) {
421 InitializeWith206Response();
422
423 ReadAt(0);
424
425 // When the read completes we'll update our network status.
426 EXPECT_CALL(host_, SetBufferedBytes(1024));
427 EXPECT_CALL(host_, SetNetworkActivity(true));
428 FinishRead();
429
430 // During teardown we'll also report our final network status.
431 EXPECT_CALL(host_, SetBufferedBytes(1024));
432 EXPECT_CALL(host_, SetNetworkActivity(false));
433 Stop();
790 } 434 }
791 435
792 } // namespace webkit_media 436 } // namespace webkit_media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698