• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include <algorithm>
6 
7 #include "base/test/test_timeouts.h"
8 #include "media/base/mock_callback.h"
9 #include "media/base/mock_filter_host.h"
10 #include "media/base/mock_filters.h"
11 #include "net/base/net_errors.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
14 #include "webkit/glue/media/buffered_data_source.h"
15 #include "webkit/mocks/mock_webframe.h"
16 
17 using ::testing::_;
18 using ::testing::Assign;
19 using ::testing::AtLeast;
20 using ::testing::DeleteArg;
21 using ::testing::DoAll;
22 using ::testing::InSequence;
23 using ::testing::Invoke;
24 using ::testing::InvokeWithoutArgs;
25 using ::testing::NotNull;
26 using ::testing::Return;
27 using ::testing::ReturnRef;
28 using ::testing::SetArgumentPointee;
29 using ::testing::StrictMock;
30 using ::testing::NiceMock;
31 using ::testing::WithArgs;
32 
33 namespace webkit_glue {
34 
35 static const char* kHttpUrl = "http://test";
36 static const char* kFileUrl = "file://test";
37 static const int kDataSize = 1024;
38 
39 enum NetworkState {
40   NONE,
41   LOADED,
42   LOADING
43 };
44 
45 // A mock BufferedDataSource to inject mock BufferedResourceLoader through
46 // CreateResourceLoader() method.
47 class MockBufferedDataSource : public BufferedDataSource {
48  public:
MockBufferedDataSource(MessageLoop * message_loop,WebFrame * frame)49   MockBufferedDataSource(MessageLoop* message_loop, WebFrame* frame)
50       : BufferedDataSource(message_loop, frame) {
51   }
52 
GetTimeoutMilliseconds()53   virtual base::TimeDelta GetTimeoutMilliseconds() {
54     return base::TimeDelta::FromMilliseconds(
55                             TestTimeouts::tiny_timeout_ms());
56   }
57 
58   MOCK_METHOD2(CreateResourceLoader,
59                BufferedResourceLoader*(int64 first_position,
60                                        int64 last_position));
61 
62  private:
63   DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource);
64 };
65 
66 class MockBufferedResourceLoader : public BufferedResourceLoader {
67  public:
MockBufferedResourceLoader()68   MockBufferedResourceLoader() : BufferedResourceLoader(GURL(), 0, 0) {
69   }
70 
71   MOCK_METHOD3(Start, void(net::CompletionCallback* read_callback,
72                            NetworkEventCallback* network_callback,
73                            WebFrame* frame));
74   MOCK_METHOD0(Stop, void());
75   MOCK_METHOD4(Read, void(int64 position, int read_size, uint8* buffer,
76                           net::CompletionCallback* callback));
77   MOCK_METHOD0(content_length, int64());
78   MOCK_METHOD0(instance_size, int64());
79   MOCK_METHOD0(range_supported, bool());
80   MOCK_METHOD0(network_activity, bool());
81   MOCK_METHOD0(url, const GURL&());
82   MOCK_METHOD0(GetBufferedFirstBytePosition, int64());
83   MOCK_METHOD0(GetBufferedLastBytePosition, int64());
84 
85  protected:
~MockBufferedResourceLoader()86   ~MockBufferedResourceLoader() {}
87 
88   DISALLOW_COPY_AND_ASSIGN(MockBufferedResourceLoader);
89 };
90 
91 class BufferedDataSourceTest : public testing::Test {
92  public:
BufferedDataSourceTest()93   BufferedDataSourceTest() {
94     message_loop_ = MessageLoop::current();
95 
96     // Prepare test data.
97     for (size_t i = 0; i < sizeof(data_); ++i) {
98       data_[i] = i;
99     }
100   }
101 
~BufferedDataSourceTest()102   virtual ~BufferedDataSourceTest() {
103   }
104 
ExpectCreateAndStartResourceLoader(int start_error)105   void ExpectCreateAndStartResourceLoader(int start_error) {
106     EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
107         .WillOnce(Return(loader_.get()));
108 
109     EXPECT_CALL(*loader_, Start(NotNull(), NotNull(), NotNull()))
110         .WillOnce(
111             DoAll(Assign(&error_, start_error),
112                   Invoke(this,
113                          &BufferedDataSourceTest::InvokeStartCallback)));
114   }
115 
InitializeDataSource(const char * url,int error,bool partial_response,int64 instance_size,NetworkState networkState)116   void InitializeDataSource(const char* url, int error,
117                             bool partial_response, int64 instance_size,
118                             NetworkState networkState) {
119     // Saves the url first.
120     gurl_ = GURL(url);
121 
122     frame_.reset(new NiceMock<MockWebFrame>());
123 
124     data_source_ = new MockBufferedDataSource(MessageLoop::current(),
125                                               frame_.get());
126     data_source_->set_host(&host_);
127 
128     scoped_refptr<NiceMock<MockBufferedResourceLoader> > first_loader(
129         new NiceMock<MockBufferedResourceLoader>());
130 
131     // Creates the mock loader to be injected.
132     loader_ = first_loader;
133 
134     bool initialized_ok = (error == net::OK);
135     bool loaded = networkState == LOADED;
136     {
137       InSequence s;
138       ExpectCreateAndStartResourceLoader(error);
139 
140       // In the case of an invalid partial response we expect a second loader
141       // to be created.
142       if (partial_response && (error == net::ERR_INVALID_RESPONSE)) {
143         // Verify that the initial loader is stopped.
144         EXPECT_CALL(*loader_, url())
145             .WillRepeatedly(ReturnRef(gurl_));
146         EXPECT_CALL(*loader_, Stop());
147 
148         // Replace loader_ with a new instance.
149         loader_ = new NiceMock<MockBufferedResourceLoader>();
150 
151         // Create and start. Make sure Start() is called on the new loader.
152         ExpectCreateAndStartResourceLoader(net::OK);
153 
154         // Update initialization variable since we know the second loader will
155         // return OK.
156         initialized_ok = true;
157       }
158     }
159 
160     // Attach a static function that deletes the memory referred by the
161     // "callback" parameter.
162     ON_CALL(*loader_, Read(_, _, _ , _))
163         .WillByDefault(DeleteArg<3>());
164 
165     ON_CALL(*loader_, instance_size())
166         .WillByDefault(Return(instance_size));
167 
168     // range_supported() return true if we expect to get a partial response.
169     ON_CALL(*loader_, range_supported())
170         .WillByDefault(Return(partial_response));
171 
172     ON_CALL(*loader_, url())
173         .WillByDefault(ReturnRef(gurl_));
174     media::PipelineStatus expected_init_status = media::PIPELINE_OK;
175     if (initialized_ok) {
176       // Expected loaded or not.
177       EXPECT_CALL(host_, SetLoaded(loaded));
178 
179       // TODO(hclam): The condition for streaming needs to be adjusted.
180       if (instance_size != -1 && (loaded || partial_response)) {
181         EXPECT_CALL(host_, SetTotalBytes(instance_size));
182         if (loaded)
183           EXPECT_CALL(host_, SetBufferedBytes(instance_size));
184         else
185           EXPECT_CALL(host_, SetBufferedBytes(0));
186       } else {
187         EXPECT_CALL(host_, SetStreaming(true));
188       }
189     } else {
190       expected_init_status = media::PIPELINE_ERROR_NETWORK;
191       EXPECT_CALL(*loader_, Stop());
192     }
193 
194     // Actual initialization of the data source.
195     data_source_->Initialize(url,
196         media::NewExpectedStatusCallback(expected_init_status));
197     message_loop_->RunAllPending();
198 
199     if (initialized_ok) {
200       // Verify the size of the data source.
201       int64 size;
202       if (instance_size != -1 && (loaded || partial_response)) {
203         EXPECT_TRUE(data_source_->GetSize(&size));
204         EXPECT_EQ(instance_size, size);
205       } else {
206         EXPECT_TRUE(data_source_->IsStreaming());
207       }
208     }
209   }
210 
StopDataSource()211   void StopDataSource() {
212     if (loader_) {
213       InSequence s;
214       EXPECT_CALL(*loader_, Stop());
215     }
216 
217     data_source_->Stop(media::NewExpectedCallback());
218     message_loop_->RunAllPending();
219   }
220 
InvokeStartCallback(net::CompletionCallback * callback,BufferedResourceLoader::NetworkEventCallback * network_callback,WebFrame * frame)221   void InvokeStartCallback(
222       net::CompletionCallback* callback,
223       BufferedResourceLoader::NetworkEventCallback* network_callback,
224       WebFrame* frame) {
225     callback->RunWithParams(Tuple1<int>(error_));
226     delete callback;
227     // TODO(hclam): Save this callback.
228     delete network_callback;
229   }
230 
InvokeReadCallback(int64 position,int size,uint8 * buffer,net::CompletionCallback * callback)231   void InvokeReadCallback(int64 position, int size, uint8* buffer,
232                           net::CompletionCallback* callback) {
233     if (error_ > 0)
234       memcpy(buffer, data_ + static_cast<int>(position), error_);
235     callback->RunWithParams(Tuple1<int>(error_));
236     delete callback;
237   }
238 
ReadDataSourceHit(int64 position,int size,int read_size)239   void ReadDataSourceHit(int64 position, int size, int read_size) {
240     EXPECT_TRUE(loader_);
241 
242     InSequence s;
243     // Expect the read is delegated to the resource loader.
244     EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
245         .WillOnce(DoAll(Assign(&error_, read_size),
246                         Invoke(this,
247                                &BufferedDataSourceTest::InvokeReadCallback)));
248 
249     // The read has succeeded, so read callback will be called.
250     EXPECT_CALL(*this, ReadCallback(read_size));
251 
252     data_source_->Read(
253         position, size, buffer_,
254         NewCallback(this, &BufferedDataSourceTest::ReadCallback));
255     message_loop_->RunAllPending();
256 
257     // Make sure data is correct.
258     EXPECT_EQ(0,
259               memcmp(buffer_, data_ + static_cast<int>(position), read_size));
260   }
261 
ReadDataSourceHang(int64 position,int size)262   void ReadDataSourceHang(int64 position, int size) {
263     EXPECT_TRUE(loader_);
264 
265     // Expect a call to read, but the call never returns.
266     EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()));
267     data_source_->Read(
268         position, size, buffer_,
269         NewCallback(this, &BufferedDataSourceTest::ReadCallback));
270     message_loop_->RunAllPending();
271 
272     // Now expect the read to return after aborting the data source.
273     EXPECT_CALL(*this, ReadCallback(_));
274     EXPECT_CALL(*loader_, Stop());
275     data_source_->Abort();
276     message_loop_->RunAllPending();
277 
278     // The loader has now been stopped. Set this to null so that when the
279     // DataSource is stopped, it does not expect a call to stop the loader.
280     loader_ = NULL;
281   }
282 
ReadDataSourceMiss(int64 position,int size,int start_error)283   void ReadDataSourceMiss(int64 position, int size, int start_error) {
284     EXPECT_TRUE(loader_);
285 
286     // 1. Reply with a cache miss for the read.
287     {
288       InSequence s;
289       EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
290           .WillOnce(DoAll(Assign(&error_, net::ERR_CACHE_MISS),
291                           Invoke(this,
292                                  &BufferedDataSourceTest::InvokeReadCallback)));
293       EXPECT_CALL(*loader_, Stop());
294     }
295 
296     // 2. Then the current loader will be stop and destroyed.
297     NiceMock<MockBufferedResourceLoader> *new_loader =
298         new NiceMock<MockBufferedResourceLoader>();
299     EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
300         .WillOnce(Return(new_loader));
301 
302     // 3. Then the new loader will be started.
303     EXPECT_CALL(*new_loader, Start(NotNull(), NotNull(), NotNull()))
304         .WillOnce(DoAll(Assign(&error_, start_error),
305                         Invoke(this,
306                                &BufferedDataSourceTest::InvokeStartCallback)));
307 
308     if (start_error == net::OK) {
309       EXPECT_CALL(*new_loader, range_supported())
310           .WillRepeatedly(Return(loader_->range_supported()));
311 
312       // 4a. Then again a read request is made to the new loader.
313       EXPECT_CALL(*new_loader, Read(position, size, NotNull(), NotNull()))
314           .WillOnce(DoAll(Assign(&error_, size),
315                           Invoke(this,
316                                  &BufferedDataSourceTest::InvokeReadCallback)));
317 
318       EXPECT_CALL(*this, ReadCallback(size));
319     } else {
320       // 4b. The read callback is called with an error because Start() on the
321       // new loader returned an error.
322       EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
323     }
324 
325     data_source_->Read(
326         position, size, buffer_,
327         NewCallback(this, &BufferedDataSourceTest::ReadCallback));
328     message_loop_->RunAllPending();
329 
330     // Make sure data is correct.
331     if (start_error == net::OK)
332       EXPECT_EQ(0, memcmp(buffer_, data_ + static_cast<int>(position), size));
333 
334     loader_ = new_loader;
335   }
336 
ReadDataSourceFailed(int64 position,int size,int error)337   void ReadDataSourceFailed(int64 position, int size, int error) {
338     EXPECT_TRUE(loader_);
339 
340     // 1. Expect the read is delegated to the resource loader.
341     EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
342         .WillOnce(DoAll(Assign(&error_, error),
343                         Invoke(this,
344                                &BufferedDataSourceTest::InvokeReadCallback)));
345 
346     // 2. Host will then receive an error.
347     EXPECT_CALL(*loader_, Stop());
348 
349     // 3. The read has failed, so read callback will be called.
350     EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
351 
352     data_source_->Read(
353         position, size, buffer_,
354         NewCallback(this, &BufferedDataSourceTest::ReadCallback));
355 
356     message_loop_->RunAllPending();
357   }
358 
ReadDataSourceTimesOut(int64 position,int size)359   void ReadDataSourceTimesOut(int64 position, int size) {
360     // 1. Drop the request and let it times out.
361     {
362       InSequence s;
363       EXPECT_CALL(*loader_, Read(position, size, NotNull(), NotNull()))
364           .WillOnce(DeleteArg<3>());
365       EXPECT_CALL(*loader_, Stop());
366     }
367 
368     // 2. Then the current loader will be stop and destroyed.
369     NiceMock<MockBufferedResourceLoader> *new_loader =
370         new NiceMock<MockBufferedResourceLoader>();
371     EXPECT_CALL(*data_source_, CreateResourceLoader(position, -1))
372         .WillOnce(Return(new_loader));
373 
374     // 3. Then the new loader will be started and respond to queries about
375     //    whether this is a partial response using the value of the previous
376     //    loader.
377     EXPECT_CALL(*new_loader, Start(NotNull(), NotNull(), NotNull()))
378         .WillOnce(DoAll(Assign(&error_, net::OK),
379                         Invoke(this,
380                                &BufferedDataSourceTest::InvokeStartCallback)));
381     EXPECT_CALL(*new_loader, range_supported())
382         .WillRepeatedly(Return(loader_->range_supported()));
383 
384     // 4. Then again a read request is made to the new loader.
385     EXPECT_CALL(*new_loader, Read(position, size, NotNull(), NotNull()))
386         .WillOnce(DoAll(Assign(&error_, size),
387                         Invoke(this,
388                                &BufferedDataSourceTest::InvokeReadCallback),
389                         InvokeWithoutArgs(message_loop_,
390                                           &MessageLoop::Quit)));
391 
392     EXPECT_CALL(*this, ReadCallback(size));
393 
394     data_source_->Read(
395         position, size, buffer_,
396         NewCallback(this, &BufferedDataSourceTest::ReadCallback));
397 
398     // This blocks the current thread until the watch task is executed and
399     // triggers a read callback to quit this message loop.
400     message_loop_->Run();
401 
402     // Make sure data is correct.
403     EXPECT_EQ(0, memcmp(buffer_, data_ + static_cast<int>(position), size));
404 
405     loader_ = new_loader;
406   }
407 
408   MOCK_METHOD1(ReadCallback, void(size_t size));
409 
410   scoped_refptr<NiceMock<MockBufferedResourceLoader> > loader_;
411   scoped_refptr<MockBufferedDataSource> data_source_;
412   scoped_ptr<NiceMock<MockWebFrame> > frame_;
413 
414   StrictMock<media::MockFilterHost> host_;
415   GURL gurl_;
416   MessageLoop* message_loop_;
417 
418   int error_;
419   uint8 buffer_[1024];
420   uint8 data_[1024];
421 
422  private:
423   DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
424 };
425 
TEST_F(BufferedDataSourceTest,InitializationSuccess)426 TEST_F(BufferedDataSourceTest, InitializationSuccess) {
427   InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
428   StopDataSource();
429 }
430 
TEST_F(BufferedDataSourceTest,InitiailizationFailed)431 TEST_F(BufferedDataSourceTest, InitiailizationFailed) {
432   InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, false, 0, NONE);
433   StopDataSource();
434 }
435 
TEST_F(BufferedDataSourceTest,MissingContentLength)436 TEST_F(BufferedDataSourceTest, MissingContentLength) {
437   InitializeDataSource(kHttpUrl, net::OK, true, -1, LOADING);
438   StopDataSource();
439 }
440 
TEST_F(BufferedDataSourceTest,RangeRequestNotSupported)441 TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) {
442   InitializeDataSource(kHttpUrl, net::OK, false, 1024, LOADING);
443   StopDataSource();
444 }
445 
446 // Test the case where we get a 206 response, but no Content-Range header.
TEST_F(BufferedDataSourceTest,MissingContentRange)447 TEST_F(BufferedDataSourceTest, MissingContentRange) {
448   InitializeDataSource(kHttpUrl, net::ERR_INVALID_RESPONSE, true, 1024,
449                        LOADING);
450   StopDataSource();
451 }
452 
TEST_F(BufferedDataSourceTest,MissingContentLengthAndRangeRequestNotSupported)453 TEST_F(BufferedDataSourceTest,
454        MissingContentLengthAndRangeRequestNotSupported) {
455   InitializeDataSource(kHttpUrl, net::OK, false, -1, LOADING);
456   StopDataSource();
457 }
458 
TEST_F(BufferedDataSourceTest,ReadCacheHit)459 TEST_F(BufferedDataSourceTest, ReadCacheHit) {
460   InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING);
461 
462   // Performs read with cache hit.
463   ReadDataSourceHit(10, 10, 10);
464 
465   // Performs read with cache hit but partially filled.
466   ReadDataSourceHit(20, 10, 5);
467 
468   StopDataSource();
469 }
470 
TEST_F(BufferedDataSourceTest,ReadCacheMiss)471 TEST_F(BufferedDataSourceTest, ReadCacheMiss) {
472   InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
473   ReadDataSourceMiss(1000, 10, net::OK);
474   ReadDataSourceMiss(20, 10, net::OK);
475   StopDataSource();
476 }
477 
478 // Test the case where the initial response from the server indicates that
479 // Range requests are supported, but a later request prove otherwise.
TEST_F(BufferedDataSourceTest,ServerLiesAboutRangeSupport)480 TEST_F(BufferedDataSourceTest, ServerLiesAboutRangeSupport) {
481   InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
482   ReadDataSourceHit(10, 10, 10);
483   ReadDataSourceMiss(1000, 10, net::ERR_INVALID_RESPONSE);
484   StopDataSource();
485 }
486 
TEST_F(BufferedDataSourceTest,ReadHang)487 TEST_F(BufferedDataSourceTest, ReadHang) {
488   InitializeDataSource(kHttpUrl, net::OK, true, 25, LOADING);
489   ReadDataSourceHang(10, 10);
490   StopDataSource();
491 }
492 
TEST_F(BufferedDataSourceTest,ReadFailed)493 TEST_F(BufferedDataSourceTest, ReadFailed) {
494   InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
495   ReadDataSourceHit(10, 10, 10);
496   ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET);
497   StopDataSource();
498 }
499 
TEST_F(BufferedDataSourceTest,ReadTimesOut)500 TEST_F(BufferedDataSourceTest, ReadTimesOut) {
501   InitializeDataSource(kHttpUrl, net::OK, true, 1024, LOADING);
502   ReadDataSourceTimesOut(20, 10);
503   StopDataSource();
504 }
505 
TEST_F(BufferedDataSourceTest,FileHasLoadedState)506 TEST_F(BufferedDataSourceTest, FileHasLoadedState) {
507   InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
508   ReadDataSourceTimesOut(20, 10);
509   StopDataSource();
510 }
511 
512 // This test makes sure that Stop() does not require a task to run on
513 // |message_loop_| before it calls its callback. This prevents accidental
514 // introduction of a pipeline teardown deadlock. The pipeline owner blocks
515 // the render message loop while waiting for Stop() to complete. Since this
516 // object runs on the render message loop, Stop() will not complete if it
517 // requires a task to run on the the message loop that is being blocked.
TEST_F(BufferedDataSourceTest,StopDoesNotUseMessageLoopForCallback)518 TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
519   InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
520 
521   // Create a callback that lets us verify that it was called before
522   // Stop() returns. This is to make sure that the callback does not
523   // require |message_loop_| to execute tasks before being called.
524   media::MockCallback* stop_callback = media::NewExpectedCallback();
525   bool stop_done_called = false;
526   ON_CALL(*stop_callback, RunWithParams(_))
527       .WillByDefault(Assign(&stop_done_called, true));
528 
529   // Stop() the data source like normal.
530   data_source_->Stop(stop_callback);
531 
532   // Verify that the callback was called inside the Stop() call.
533   EXPECT_TRUE(stop_done_called);
534 
535   message_loop_->RunAllPending();
536 }
537 
TEST_F(BufferedDataSourceTest,AbortDuringPendingRead)538 TEST_F(BufferedDataSourceTest, AbortDuringPendingRead) {
539   InitializeDataSource(kFileUrl, net::OK, true, 1024, LOADED);
540 
541   // Setup a way to verify that Read() is not called on the loader.
542   // We are doing this to make sure that the ReadTask() is still on
543   // the message loop queue when Abort() is called.
544   bool read_called = false;
545   ON_CALL(*loader_, Read(_, _, _ , _))
546       .WillByDefault(DoAll(Assign(&read_called, true),
547                            DeleteArg<3>()));
548 
549   // Initiate a Read() on the data source, but don't allow the
550   // message loop to run.
551   data_source_->Read(
552       0, 10, buffer_,
553       NewCallback(static_cast<BufferedDataSourceTest*>(this),
554                   &BufferedDataSourceTest::ReadCallback));
555 
556   // Call Abort() with the read pending.
557   EXPECT_CALL(*this, ReadCallback(-1));
558   EXPECT_CALL(*loader_, Stop());
559   data_source_->Abort();
560 
561   // Verify that Read()'s after the Abort() issue callback with an error.
562   EXPECT_CALL(*this, ReadCallback(-1));
563   data_source_->Read(
564       0, 10, buffer_,
565       NewCallback(static_cast<BufferedDataSourceTest*>(this),
566                   &BufferedDataSourceTest::ReadCallback));
567 
568   // Stop() the data source like normal.
569   data_source_->Stop(media::NewExpectedCallback());
570 
571   // Allow cleanup task to run.
572   message_loop_->RunAllPending();
573 
574   // Verify that Read() was not called on the loader.
575   EXPECT_FALSE(read_called);
576 }
577 
578 }  // namespace webkit_glue
579