Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 13 #include "webkit/media/response_generator.h" | |
| 18 #include "webkit/mocks/mock_webframeclient.h" | 14 #include "webkit/mocks/mock_webframeclient.h" |
| 19 #include "webkit/mocks/mock_weburlloader.h" | 15 #include "webkit/mocks/mock_weburlloader.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; | |
| 39 using WebKit::WebURLError; | |
| 40 using WebKit::WebURLResponse; | 25 using WebKit::WebURLResponse; |
| 41 using WebKit::WebView; | 26 using WebKit::WebView; |
| 42 | 27 |
| 43 using webkit_glue::MockWebFrameClient; | 28 using webkit_glue::MockWebFrameClient; |
| 44 using webkit_glue::MockWebURLLoader; | 29 using webkit_glue::MockWebURLLoader; |
| 45 | 30 |
| 46 namespace webkit_media { | 31 namespace webkit_media { |
| 47 | 32 |
| 48 static const char* kHttpUrl = "http://test"; | 33 // Overrides CreateResourceLoader() to permit injecting a MockWebURLLoader. |
| 49 static const char* kFileUrl = "file://test"; | 34 // 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 { | 35 class MockBufferedDataSource : public BufferedDataSource { |
| 62 public: | 36 public: |
| 63 MockBufferedDataSource(MessageLoop* message_loop, WebFrame* frame) | 37 MockBufferedDataSource(MessageLoop* message_loop, WebFrame* frame) |
| 64 : BufferedDataSource(message_loop, frame, new media::MediaLog()) { | 38 : BufferedDataSource(message_loop, frame, new media::MediaLog()), |
| 65 } | 39 loading_(false) { |
| 66 | 40 } |
| 67 virtual base::TimeDelta GetTimeoutMilliseconds() { | 41 |
| 68 return base::TimeDelta::FromMilliseconds( | 42 MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*(int64, int64)); |
| 69 TestTimeouts::tiny_timeout_ms()); | 43 BufferedResourceLoader* CreateMockResourceLoader(int64 first_byte_position, |
| 70 } | 44 int64 last_byte_position) { |
| 71 | 45 CHECK(!loading_) << "Previous resource load wasn't cancelled"; |
| 72 MOCK_METHOD2(CreateResourceLoader, | 46 |
| 73 BufferedResourceLoader*(int64 first_position, | 47 BufferedResourceLoader* loader = |
| 74 int64 last_position)); | 48 BufferedDataSource::CreateResourceLoader(first_byte_position, |
| 49 last_byte_position); | |
| 50 | |
| 51 // Keep track of active loading state via loadAsynchronously() and cancel(). | |
| 52 NiceMock<MockWebURLLoader>* url_loader = new NiceMock<MockWebURLLoader>(); | |
| 53 ON_CALL(*url_loader, loadAsynchronously(_, _)) | |
| 54 .WillByDefault(Assign(&loading_, true)); | |
| 55 ON_CALL(*url_loader, cancel()) | |
| 56 .WillByDefault(Assign(&loading_, false)); | |
| 57 | |
| 58 // TODO(scherkus): this is a real leak detected by http://crbug.com/100914 | |
| 59 // but the fix will have to wait for a more invasive follow up patch. | |
| 60 // | |
| 61 // If you're curious what the fix is, we no longer need the reference | |
| 62 // counting added to BufferedResourceLoader in r23274 since we started | |
| 63 // using WebURLLoader in r69429. | |
| 64 Mock::AllowLeak(url_loader); | |
| 65 | |
| 66 loader->SetURLLoaderForTest(url_loader); | |
| 67 return loader; | |
| 68 } | |
| 69 | |
| 70 bool loading() { return loading_; } | |
| 71 void set_loading(bool loading) { loading_ = loading; } | |
| 75 | 72 |
| 76 private: | 73 private: |
| 74 // Whether the resource load has starting loading but yet to been cancelled. | |
| 75 bool loading_; | |
| 76 | |
| 77 DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource); | 77 DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource); |
| 78 }; | 78 }; |
| 79 | 79 |
| 80 class MockBufferedResourceLoader : public BufferedResourceLoader { | |
| 81 public: | |
| 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 | |
| 107 class BufferedDataSourceTest : public testing::Test { | 80 class BufferedDataSourceTest : public testing::Test { |
| 108 public: | 81 public: |
| 109 BufferedDataSourceTest() | 82 BufferedDataSourceTest() |
| 110 : view_(WebView::create(NULL)) { | 83 : responses_(GURL("http://localhost/foo.webm"), 5000000), |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
Can this 5M (and the 4M elsewhere in this file) be
scherkus (not reviewing)
2011/11/23 04:22:41
the 5M/4M are test specific but I'll go ahead and
| |
| 84 view_(WebView::create(NULL)), | |
| 85 message_loop_(MessageLoop::current()) { | |
| 111 view_->initializeMainFrame(&client_); | 86 view_->initializeMainFrame(&client_); |
| 112 message_loop_ = MessageLoop::current(); | 87 |
| 113 | 88 data_source_ = new MockBufferedDataSource(message_loop_, |
| 114 for (size_t i = 0; i < sizeof(data_); ++i) { | 89 view_->mainFrame()); |
| 115 data_[i] = i; | 90 data_source_->set_host(&host_); |
| 116 } | |
| 117 } | 91 } |
| 118 | 92 |
| 119 virtual ~BufferedDataSourceTest() { | 93 virtual ~BufferedDataSourceTest() { |
| 120 view_->close(); | 94 view_->close(); |
| 121 } | 95 } |
| 122 | 96 |
| 123 void ExpectCreateAndStartResourceLoader(int start_error) { | 97 void Initialize(media::PipelineStatus expected) { |
| 98 data_source_->Initialize(responses_.gurl().spec(), | |
| 99 media::NewExpectedStatusCB(expected)); | |
| 100 message_loop_->RunAllPending(); | |
| 101 } | |
| 102 | |
| 103 // Helper to initialize tests with a valid 206 response. | |
| 104 void InitializeWith206Response() { | |
| 105 ExpectCreateResourceLoader(); | |
| 106 Initialize(media::PIPELINE_OK); | |
| 107 | |
| 108 EXPECT_CALL(host_, SetLoaded(false)); | |
| 109 EXPECT_CALL(host_, SetTotalBytes(responses_.content_length())); | |
| 110 EXPECT_CALL(host_, SetBufferedBytes(0)); | |
| 111 Respond(responses_.Generate206(0)); | |
| 112 } | |
| 113 | |
| 114 // Stops all active loaders and shuts down the data source. | |
| 115 // | |
| 116 // This typically happens when the page is closed and for our purposes is | |
| 117 // appropriate to do when tearing down a test. | |
| 118 void Stop() { | |
| 119 CHECK(data_source_->loading()) | |
| 120 << "You don't need to stop if there is nothing loading"; | |
| 121 | |
| 122 loader()->didFail(url_loader(), responses_.GenerateError()); | |
| 123 message_loop_->RunAllPending(); | |
| 124 | |
| 125 data_source_->Stop(media::NewExpectedClosure()); | |
| 126 message_loop_->RunAllPending(); | |
| 127 } | |
| 128 | |
| 129 void ExpectCreateResourceLoader() { | |
| 124 EXPECT_CALL(*data_source_, CreateResourceLoader(_, _)) | 130 EXPECT_CALL(*data_source_, CreateResourceLoader(_, _)) |
| 125 .WillOnce(Return(loader_.get())); | 131 .WillOnce(Invoke(data_source_.get(), |
| 126 | 132 &MockBufferedDataSource::CreateMockResourceLoader)); |
| 127 EXPECT_CALL(*loader_, Start(NotNull(), _, NotNull())) | 133 message_loop_->RunAllPending(); |
| 128 .WillOnce( | 134 } |
| 129 DoAll(Assign(&error_, start_error), | 135 |
| 130 Invoke(this, | 136 void Respond(const WebURLResponse& response) { |
| 131 &BufferedDataSourceTest::InvokeStartCallback))); | 137 loader()->didReceiveResponse(url_loader(), response); |
| 132 } | 138 message_loop_->RunAllPending(); |
| 133 | 139 } |
| 134 void InitializeDataSource(const char* url, int error, | 140 |
| 135 bool partial_response, int64 instance_size, | 141 void FinishRead() { |
| 136 NetworkState networkState) { | 142 loader()->didReceiveData(url_loader(), data_, kDataSize, kDataSize); |
| 137 // Saves the url first. | 143 message_loop_->RunAllPending(); |
| 138 gurl_ = GURL(url); | 144 } |
| 139 | 145 |
| 140 data_source_ = new MockBufferedDataSource(MessageLoop::current(), | 146 void FinishLoading() { |
| 141 view_->mainFrame()); | 147 data_source_->set_loading(false); |
| 142 data_source_->set_host(&host_); | 148 loader()->didFinishLoading(url_loader(), 0); |
| 143 | 149 message_loop_->RunAllPending(); |
| 144 scoped_refptr<NiceMock<MockBufferedResourceLoader> > first_loader( | 150 } |
| 145 new NiceMock<MockBufferedResourceLoader>()); | 151 |
| 146 | 152 MOCK_METHOD1(ReadCallback, void(size_t size)); |
| 147 // Creates the mock loader to be injected. | 153 |
| 148 loader_ = first_loader; | 154 void ReadAt(int64 position) { |
| 149 | 155 EXPECT_CALL(*this, ReadCallback(kDataSize)); |
| 150 bool initialized_ok = (error == net::OK); | 156 data_source_->Read(position, kDataSize, buffer_, |
| 151 bool loaded = networkState == LOADED; | 157 base::Bind(&BufferedDataSourceTest::ReadCallback, |
| 152 { | 158 base::Unretained(this))); |
| 153 InSequence s; | 159 message_loop_->RunAllPending(); |
| 154 ExpectCreateAndStartResourceLoader(error); | 160 } |
| 155 | 161 |
| 156 // In the case of an invalid partial response we expect a second loader | 162 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)); | 163 EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); |
| 370 | 164 data_source_->Read(position, kDataSize, buffer_, |
| 371 data_source_->Read( | 165 base::Bind(&BufferedDataSourceTest::ReadCallback, |
| 372 position, size, buffer_, | 166 base::Unretained(this))); |
| 373 base::Bind(&BufferedDataSourceTest::ReadCallback, | 167 message_loop_->RunAllPending(); |
| 374 base::Unretained(this))); | 168 } |
| 375 | 169 |
| 376 message_loop_->RunAllPending(); | 170 // Accessors for private variables on |data_source_|. |
| 377 } | 171 BufferedResourceLoader* loader() { |
| 378 | 172 return data_source_->loader_.get(); |
| 379 BufferedResourceLoader* InvokeCacheMissCreateResourceLoader(int64 start, | 173 } |
| 380 int64 end) { | 174 NiceMock<MockWebURLLoader>* url_loader() { |
| 381 NiceMock<MockBufferedResourceLoader>* new_loader = | 175 return static_cast<NiceMock<MockWebURLLoader>*>( |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
Does this really need to return the Mock subtype (
scherkus (not reviewing)
2011/11/23 04:22:41
Nope!
It used to but we no longer require the moc
| |
| 382 new NiceMock<MockBufferedResourceLoader>(); | 176 loader()->url_loader_.get()); |
| 383 | 177 } |
| 384 EXPECT_CALL(*new_loader, Start(NotNull(), _, NotNull())) | 178 |
| 385 .WillOnce(DoAll(Assign(&error_, net::OK), | 179 media::Preload preload() { return data_source_->preload_; } |
| 386 Invoke(this, | 180 BufferedResourceLoader::DeferStrategy defer_strategy() { |
| 387 &BufferedDataSourceTest::InvokeStartCallback))); | 181 return loader()->defer_strategy_; |
| 388 | 182 } |
| 389 EXPECT_CALL(*new_loader, range_supported()) | 183 int data_source_bitrate() { return data_source_->bitrate_; } |
| 390 .WillRepeatedly(Return(loader_->range_supported())); | 184 int data_source_playback_rate() { return data_source_->playback_rate_; } |
| 391 | 185 int loader_bitrate() { return loader()->bitrate_; } |
| 392 int error = net::ERR_FAILED; | 186 int loader_playback_rate() { return loader()->playback_rate_; } |
| 393 if (cache_miss_count_ < kMaxCacheMissesBeforeFailTest) { | 187 |
| 394 cache_miss_count_++; | 188 |
| 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_; | 189 scoped_refptr<MockBufferedDataSource> data_source_; |
| 436 | 190 |
| 191 ResponseGenerator responses_; | |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
s/responses_/response_generator_/
scherkus (not reviewing)
2011/11/23 04:22:41
Done.
| |
| 437 MockWebFrameClient client_; | 192 MockWebFrameClient client_; |
| 438 WebView* view_; | 193 WebView* view_; |
| 439 | 194 |
| 440 StrictMock<media::MockFilterHost> host_; | 195 StrictMock<media::MockFilterHost> host_; |
| 441 GURL gurl_; | |
| 442 MessageLoop* message_loop_; | 196 MessageLoop* message_loop_; |
| 443 | 197 |
| 444 int error_; | |
| 445 uint8 buffer_[1024]; | |
| 446 uint8 data_[1024]; | |
| 447 | |
| 448 int cache_miss_count_; | |
| 449 | |
| 450 private: | 198 private: |
| 199 static const size_t kDataSize = 1024; | |
| 200 | |
| 201 // Used for calling BufferedDataSource::Read(). | |
| 202 uint8 buffer_[kDataSize]; | |
| 203 | |
| 204 // Used for calling BufferedResourceLoader::didReceiveData(). | |
| 205 char data_[kDataSize]; | |
| 206 | |
| 451 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest); | 207 DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest); |
| 452 }; | 208 }; |
| 453 | 209 |
| 454 TEST_F(BufferedDataSourceTest, InitializationSuccess) { | 210 TEST_F(BufferedDataSourceTest, Range_Supported) { |
| 455 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); | 211 ExpectCreateResourceLoader(); |
| 456 StopDataSource(); | 212 Initialize(media::PIPELINE_OK); |
| 457 } | 213 |
| 458 | 214 EXPECT_CALL(host_, SetLoaded(false)); |
| 459 TEST_F(BufferedDataSourceTest, InitiailizationFailed) { | 215 EXPECT_CALL(host_, SetTotalBytes(responses_.content_length())); |
| 460 InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, false, 0, NONE); | 216 EXPECT_CALL(host_, SetBufferedBytes(0)); |
| 461 StopDataSource(); | 217 Respond(responses_.Generate206(0)); |
| 462 } | 218 Stop(); |
| 463 | 219 } |
| 464 TEST_F(BufferedDataSourceTest, MissingContentLength) { | 220 |
| 465 InitializeDataSource(kHttpUrl, net::OK, true, -1, LOADING); | 221 TEST_F(BufferedDataSourceTest, Range_NotFound) { |
| 466 StopDataSource(); | 222 ExpectCreateResourceLoader(); |
| 467 } | 223 Initialize(media::PIPELINE_ERROR_NETWORK); |
| 468 | 224 |
| 469 TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) { | 225 // It'll try again. |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
(here and below)
Is this business of blindly retry
scherkus (not reviewing)
2011/11/23 04:22:41
bug worthy
| |
| 470 InitializeDataSource(kHttpUrl, net::OK, false, 1024, LOADING); | 226 ExpectCreateResourceLoader(); |
| 471 StopDataSource(); | 227 Respond(responses_.Generate404()); |
| 472 } | 228 |
| 473 | 229 // Now it's done and will fail. |
| 474 // Test the case where we get a 206 response, but no Content-Range header. | 230 Respond(responses_.Generate404()); |
| 475 TEST_F(BufferedDataSourceTest, MissingContentRange) { | 231 } |
| 476 InitializeDataSource(kHttpUrl, net::ERR_INVALID_RESPONSE, true, 1024, | 232 |
| 477 LOADING); | 233 TEST_F(BufferedDataSourceTest, Range_NotSupported) { |
| 478 StopDataSource(); | 234 ExpectCreateResourceLoader(); |
| 479 } | 235 Initialize(media::PIPELINE_OK); |
| 480 | 236 |
| 481 TEST_F(BufferedDataSourceTest, | 237 // It'll try again. |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
I think we have a crbug to realize range->200 shou
scherkus (not reviewing)
2011/11/23 04:22:41
Done.
| |
| 482 MissingContentLengthAndRangeRequestNotSupported) { | 238 ExpectCreateResourceLoader(); |
| 483 InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING); | 239 Respond(responses_.Generate200()); |
| 484 StopDataSource(); | 240 |
| 485 } | 241 // Now it'll succeed. |
| 486 | 242 EXPECT_CALL(host_, SetLoaded(false)); |
| 487 TEST_F(BufferedDataSourceTest, ReadCacheHit) { | 243 EXPECT_CALL(host_, SetTotalBytes(responses_.content_length())); |
| 488 InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); | 244 EXPECT_CALL(host_, SetBufferedBytes(0)); |
| 489 | 245 EXPECT_CALL(host_, SetStreaming(true)); |
| 490 // Performs read with cache hit. | 246 Respond(responses_.Generate200()); |
| 491 ReadDataSourceHit(10, 10, 10); | 247 Stop(); |
| 492 | 248 } |
| 493 // Performs read with cache hit but partially filled. | 249 |
| 494 ReadDataSourceHit(20, 10, 5); | 250 TEST_F(BufferedDataSourceTest, Range_MissingContentRange) { |
| 495 | 251 ExpectCreateResourceLoader(); |
| 496 StopDataSource(); | 252 Initialize(media::PIPELINE_ERROR_NETWORK); |
| 497 } | 253 |
| 498 | 254 // It'll try again. |
| 499 TEST_F(BufferedDataSourceTest, ReadCacheMiss) { | 255 ExpectCreateResourceLoader(); |
| 500 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); | 256 Respond(responses_.Generate206(0, ResponseGenerator::kNoContentRange)); |
| 501 ReadDataSourceMiss(1000, 10, net::OK); | 257 |
| 502 ReadDataSourceMiss(20, 10, net::OK); | 258 // Now it's done and will fail. |
| 503 StopDataSource(); | 259 Respond(responses_.Generate206(0, ResponseGenerator::kNoContentRange)); |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
Shouldn't this be failing back to a non-range requ
scherkus (not reviewing)
2011/11/23 04:22:41
this is a 206 response that's missing content rang
| |
| 260 } | |
| 261 | |
| 262 TEST_F(BufferedDataSourceTest, Range_MissingContentLength) { | |
| 263 ExpectCreateResourceLoader(); | |
| 264 Initialize(media::PIPELINE_OK); | |
| 265 | |
| 266 // It'll manage without a Content-Length response. | |
| 267 EXPECT_CALL(host_, SetLoaded(false)); | |
| 268 EXPECT_CALL(host_, SetTotalBytes(responses_.content_length())); | |
| 269 EXPECT_CALL(host_, SetBufferedBytes(0)); | |
| 270 Respond(responses_.Generate206(0, ResponseGenerator::kNoContentLength)); | |
| 271 Stop(); | |
| 272 } | |
| 273 | |
| 274 TEST_F(BufferedDataSourceTest, Range_WrongContentRange) { | |
| 275 ExpectCreateResourceLoader(); | |
| 276 Initialize(media::PIPELINE_ERROR_NETWORK); | |
| 277 | |
| 278 // It'll try again. | |
| 279 ExpectCreateResourceLoader(); | |
| 280 Respond(responses_.Generate206(1337)); | |
| 281 | |
| 282 // Now it's done and will fail. | |
| 283 Respond(responses_.Generate206(1337)); | |
| 504 } | 284 } |
| 505 | 285 |
| 506 // Test the case where the initial response from the server indicates that | 286 // Test the case where the initial response from the server indicates that |
| 507 // Range requests are supported, but a later request prove otherwise. | 287 // Range requests are supported, but a later request prove otherwise. |
| 508 TEST_F(BufferedDataSourceTest, ServerLiesAboutRangeSupport) { | 288 TEST_F(BufferedDataSourceTest, Range_ServerLied) { |
| 509 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); | 289 InitializeWith206Response(); |
| 510 ReadDataSourceHit(10, 10, 10); | 290 |
| 511 ReadDataSourceMiss(1000, 10, net::ERR_INVALID_RESPONSE); | 291 // Read causing a new request to be made -- we'll expect it to error. |
| 512 StopDataSource(); | 292 ExpectCreateResourceLoader(); |
| 513 } | 293 ReadAtWithError(4000000); |
| 514 | 294 |
| 515 TEST_F(BufferedDataSourceTest, ReadHang) { | 295 // Return a 200 in response to a range request. |
| 516 InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING); | 296 Respond(responses_.Generate200()); |
| 517 ReadDataSourceHang(10, 10); | 297 } |
| 518 StopDataSource(); | 298 |
| 519 } | 299 TEST_F(BufferedDataSourceTest, Range_AbortWhileReading) { |
| 520 | 300 InitializeWith206Response(); |
| 521 TEST_F(BufferedDataSourceTest, ReadFailed) { | 301 |
| 522 InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING); | 302 // Make sure there's a pending read -- we'll expect it to error. |
| 523 ReadDataSourceHit(10, 10, 10); | 303 ReadAtWithError(0); |
| 524 ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET); | 304 |
| 525 StopDataSource(); | 305 // Abort!!! |
| 526 } | 306 data_source_->Abort(); |
| 527 | 307 message_loop_->RunAllPending(); |
| 528 // Helper that sets |*value| to true. Useful for binding into a Closure. | 308 } |
| 309 | |
| 310 TEST_F(BufferedDataSourceTest, Range_TooManyRetries) { | |
| 311 InitializeWith206Response(); | |
| 312 | |
| 313 // Make sure there's a pending read -- we'll expect it to error. | |
| 314 ReadAtWithError(0); | |
| 315 | |
| 316 // It'll try three times. | |
| 317 ExpectCreateResourceLoader(); | |
| 318 FinishLoading(); | |
| 319 Respond(responses_.Generate206(0)); | |
| 320 | |
| 321 ExpectCreateResourceLoader(); | |
| 322 FinishLoading(); | |
| 323 Respond(responses_.Generate206(0)); | |
| 324 | |
| 325 ExpectCreateResourceLoader(); | |
| 326 FinishLoading(); | |
| 327 Respond(responses_.Generate206(0)); | |
| 328 | |
| 329 // It'll error after this. | |
|
Ami GONE FROM CHROMIUM
2011/11/22 22:06:23
I wish expecting an error in all these tests didn'
scherkus (not reviewing)
2011/11/23 04:22:41
The reason I don't call Stop() is because we don't
Ami GONE FROM CHROMIUM
2011/11/24 01:20:38
Your choice (maybe code it and see what it looks l
| |
| 330 FinishLoading(); | |
| 331 } | |
| 332 | |
| 529 static void SetTrue(bool* value) { | 333 static void SetTrue(bool* value) { |
| 530 *value = true; | 334 *value = true; |
| 531 } | 335 } |
| 532 | 336 |
| 533 // This test makes sure that Stop() does not require a task to run on | 337 // 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 | 338 // |message_loop_| before it calls its callback. This prevents accidental |
| 535 // introduction of a pipeline teardown deadlock. The pipeline owner blocks | 339 // introduction of a pipeline teardown deadlock. The pipeline owner blocks |
| 536 // the render message loop while waiting for Stop() to complete. Since this | 340 // 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 | 341 // 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. | 342 // requires a task to run on the the message loop that is being blocked. |
| 539 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) { | 343 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) { |
| 540 InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); | 344 InitializeWith206Response(); |
| 541 | 345 |
| 542 // Stop() the data source, using a callback that lets us verify that it was | 346 // 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 | 347 // called before Stop() returns. This is to make sure that the callback does |
| 544 // not require |message_loop_| to execute tasks before being called. | 348 // not require |message_loop_| to execute tasks before being called. |
| 545 bool stop_done_called = false; | 349 bool stop_done_called = false; |
| 546 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called)); | 350 data_source_->Stop(base::Bind(&SetTrue, &stop_done_called)); |
| 547 | 351 |
| 548 // Verify that the callback was called inside the Stop() call. | 352 // Verify that the callback was called inside the Stop() call. |
| 549 EXPECT_TRUE(stop_done_called); | 353 EXPECT_TRUE(stop_done_called); |
| 550 | |
| 551 message_loop_->RunAllPending(); | 354 message_loop_->RunAllPending(); |
| 552 } | 355 } |
| 553 | 356 |
| 554 TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) { | 357 TEST_F(BufferedDataSourceTest, DefaultValues) { |
| 555 InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED); | 358 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 | 359 |
| 734 // Ensure we have sane values for default loading scenario. | 360 // Ensure we have sane values for default loading scenario. |
| 735 EXPECT_EQ(media::AUTO, preload()); | 361 EXPECT_EQ(media::AUTO, preload()); |
| 736 EXPECT_EQ(BufferedResourceLoader::kThresholdDefer, defer_strategy()); | 362 EXPECT_EQ(BufferedResourceLoader::kThresholdDefer, defer_strategy()); |
| 737 | 363 |
| 738 EXPECT_EQ(0, data_source_bitrate()); | 364 EXPECT_EQ(0, data_source_bitrate()); |
| 739 EXPECT_EQ(0.0f, data_source_playback_rate()); | 365 EXPECT_EQ(0.0f, data_source_playback_rate()); |
| 740 EXPECT_EQ(0, loader_bitrate()); | 366 EXPECT_EQ(0, loader_bitrate()); |
| 741 EXPECT_EQ(0.0f, loader_playback_rate()); | 367 EXPECT_EQ(0.0f, loader_playback_rate()); |
| 742 | 368 Stop(); |
| 743 StopDataSource(); | |
| 744 } | 369 } |
| 745 | 370 |
| 746 TEST_F(BufferedDataSourceTest2, SetBitrate) { | 371 TEST_F(BufferedDataSourceTest, SetBitrate) { |
| 747 InitializeDataSource("http://localhost/foo.webm"); | 372 InitializeWith206Response(); |
| 748 | 373 |
| 749 data_source_->SetBitrate(1234); | 374 data_source_->SetBitrate(1234); |
| 750 message_loop_->RunAllPending(); | 375 message_loop_->RunAllPending(); |
| 751 EXPECT_EQ(1234, data_source_bitrate()); | 376 EXPECT_EQ(1234, data_source_bitrate()); |
| 752 EXPECT_EQ(1234, loader_bitrate()); | 377 EXPECT_EQ(1234, loader_bitrate()); |
| 753 | 378 |
| 754 // Read so far ahead to cause the loader to get recreated. | 379 // Read so far ahead to cause the loader to get recreated. |
| 755 BufferedResourceLoader* old_loader = data_source_->loader(); | 380 BufferedResourceLoader* old_loader = loader(); |
| 756 | 381 ExpectCreateResourceLoader(); |
| 757 uint8 buffer[1024]; | 382 ReadAtWithError(4000000); |
| 758 data_source_->Read(4000000, 1024, buffer, | 383 Respond(responses_.Generate206(4000000)); |
| 759 NewReadCallback(media::DataSource::kReadError)); | |
| 760 message_loop_->RunAllPending(); | |
| 761 | 384 |
| 762 // Verify loader changed but still has same bitrate. | 385 // Verify loader changed but still has same bitrate. |
| 763 EXPECT_NE(old_loader, data_source_->loader().get()); | 386 EXPECT_NE(old_loader, loader()); |
| 764 EXPECT_EQ(1234, loader_bitrate()); | 387 EXPECT_EQ(1234, loader_bitrate()); |
| 765 | 388 Stop(); |
| 766 StopDataSource(); | |
| 767 } | 389 } |
| 768 | 390 |
| 769 TEST_F(BufferedDataSourceTest2, SetPlaybackRate) { | 391 TEST_F(BufferedDataSourceTest, SetPlaybackRate) { |
| 770 InitializeDataSource("http://localhost/foo.webm"); | 392 InitializeWith206Response(); |
| 771 | 393 |
| 772 data_source_->SetPlaybackRate(2.0f); | 394 data_source_->SetPlaybackRate(2.0f); |
| 773 message_loop_->RunAllPending(); | 395 message_loop_->RunAllPending(); |
| 774 EXPECT_EQ(2.0f, data_source_playback_rate()); | 396 EXPECT_EQ(2.0f, data_source_playback_rate()); |
| 775 EXPECT_EQ(2.0f, loader_playback_rate()); | 397 EXPECT_EQ(2.0f, loader_playback_rate()); |
| 776 | 398 |
| 777 // Read so far ahead to cause the loader to get recreated. | 399 // Read so far ahead to cause the loader to get recreated. |
| 778 BufferedResourceLoader* old_loader = data_source_->loader(); | 400 BufferedResourceLoader* old_loader = loader(); |
| 779 | 401 ExpectCreateResourceLoader(); |
| 780 uint8 buffer[1024]; | 402 ReadAtWithError(4000000); |
| 781 data_source_->Read(4000000, 1024, buffer, | 403 Respond(responses_.Generate206(4000000)); |
| 782 NewReadCallback(media::DataSource::kReadError)); | |
| 783 message_loop_->RunAllPending(); | |
| 784 | 404 |
| 785 // Verify loader changed but still has same bitrate. | 405 // Verify loader changed but still has same bitrate. |
| 786 EXPECT_NE(old_loader, data_source_->loader().get()); | 406 EXPECT_NE(old_loader, loader()); |
| 787 EXPECT_EQ(2.0f, loader_playback_rate()); | 407 Stop(); |
| 408 } | |
| 788 | 409 |
| 789 StopDataSource(); | 410 TEST_F(BufferedDataSourceTest, Read) { |
| 411 InitializeWith206Response(); | |
| 412 | |
| 413 ReadAt(0); | |
| 414 | |
| 415 // When the read completes we'll update our network status. | |
| 416 EXPECT_CALL(host_, SetBufferedBytes(1024)); | |
| 417 EXPECT_CALL(host_, SetNetworkActivity(true)); | |
| 418 FinishRead(); | |
| 419 | |
| 420 // During teardown we'll also report our final network status. | |
| 421 EXPECT_CALL(host_, SetBufferedBytes(1024)); | |
| 422 EXPECT_CALL(host_, SetNetworkActivity(false)); | |
| 423 Stop(); | |
| 790 } | 424 } |
| 791 | 425 |
| 792 } // namespace webkit_media | 426 } // namespace webkit_media |
| OLD | NEW |