OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "base/bind.h" | |
6 #include "base/callback_helpers.h" | |
7 #include "base/message_loop.h" | |
8 #include "media/base/composite_filter.h" | |
9 #include "media/base/mock_callback.h" | |
10 #include "media/base/mock_filter_host.h" | |
11 #include "media/base/mock_filters.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 using ::testing::_; | |
15 using ::testing::InSequence; | |
16 using ::testing::Return; | |
17 using ::testing::SaveArg; | |
18 using ::testing::StrictMock; | |
19 | |
20 namespace media { | |
21 | |
22 class CompositeFilterTest : public testing::Test { | |
23 public: | |
24 CompositeFilterTest(); | |
25 virtual ~CompositeFilterTest(); | |
26 | |
27 // Sets up a new CompositeFilter in |composite_|, creates |filter_1_| and | |
28 // |filter_2_|, and adds these filters to |composite_|. | |
29 void SetupAndAdd2Filters(); | |
30 | |
31 // Helper enum that indicates what filter method to call. | |
32 enum MethodToCall { | |
33 PLAY, | |
34 PAUSE, | |
35 FLUSH, | |
36 STOP, | |
37 SEEK, | |
38 }; | |
39 | |
40 // Helper method that adds a filter method call expectation based on the value | |
41 // of |method_to_call|. | |
42 // | |
43 // |method_to_call| - Indicates which method we expect a call for. | |
44 // |filter| - The MockFilter to add the expectation to. | |
45 // |seek_time| - The time to pass to the Seek() call if |method_to_call| | |
46 // equals SEEK. | |
47 void ExpectFilterCall(MethodToCall method_to_call, MockFilter* filter, | |
48 base::TimeDelta seek_time); | |
49 | |
50 // Helper method that calls a filter method based on the value of | |
51 // |method_to_call|. | |
52 // | |
53 // |method_to_call| - Indicates which method to call. | |
54 // |filter| - The Filter to make the method call on. | |
55 // |seek_time| - The time to pass to the Seek() call if |method_to_call| | |
56 // equals SEEK. | |
57 // |callback| - The callback object to pass to the method. | |
58 // |expected_status| - Some filter methods use a PipelineStatusCB instead of | |
59 // a Closure. For these methods this function | |
60 // creates a PipelineStatusCB that makes sure the status | |
61 // passed to the callback matches |expected_status| and | |
62 // then calls |callback|. | |
63 void DoFilterCall(MethodToCall method_to_call, Filter* filter, | |
64 base::TimeDelta seek_time, | |
65 const base::Closure& callback, | |
66 PipelineStatus expected_status); | |
67 | |
68 // Creates an expectation sequence based on the value of method_to_call. | |
69 // | |
70 // |method_to_call| - Indicates which method we want a success sequence for. | |
71 // |seek_time| - The time to pass in the Seek() call if |method_to_call| | |
72 // equals SEEK. | |
73 void ExpectSuccess(MethodToCall method_to_call, | |
74 base::TimeDelta seek_time = base::TimeDelta()); | |
75 | |
76 // Issue a Play(), Pause(), Flush(), Stop(), or Seek() on the composite and | |
77 // verify all the expected calls on the filters. | |
78 void DoPlay(); | |
79 void DoPause(); | |
80 void DoFlush(); | |
81 void DoStop(); | |
82 void DoSeek(base::TimeDelta time); | |
83 | |
84 // Issue a Play(), Pause(), Flush(), or Seek() and expect the calls to fail | |
85 // with a PIPELINE_ERROR_INVALID_STATE error. | |
86 // | |
87 // |method_to_call| - Indicates whick method to call. | |
88 // |seek_time| - The time to pass to the Seek() call if |method_to_call| | |
89 // equals SEEK. | |
90 void ExpectInvalidStateFail(MethodToCall method_to_call, | |
91 base::TimeDelta seek_time = base::TimeDelta()); | |
92 | |
93 // Returns whether |filter_1_cb_| or |filter_1_status_cb_| is set. | |
94 bool HasFilter1Callback() const; | |
95 | |
96 // Run the callback stored in |filter_1_cb_| or |filter_2_status_cb_|. | |
97 void RunFilter1Callback(); | |
98 | |
99 // Returns whether |filter_2_cb_| or |filter_2_status_cb_| is set. | |
100 bool HasFilter2Callback() const; | |
101 | |
102 // Run the callback stored in |filter_2_cb_| or |filter_2_status_cb_|. | |
103 void RunFilter2Callback(); | |
104 | |
105 protected: | |
106 MessageLoop message_loop_; | |
107 | |
108 // The composite object being tested. | |
109 scoped_refptr<CompositeFilter> composite_; | |
110 | |
111 // First filter added to the composite. | |
112 scoped_refptr<StrictMock<MockFilter> > filter_1_; | |
113 | |
114 // Callback passed to |filter_1_| during last Play(), Pause(), Flush(), | |
115 // or Stop() call. | |
116 base::Closure filter_1_cb_; | |
117 | |
118 // Status to pass to |filter_1_status_cb_|. | |
119 PipelineStatus filter_1_status_; | |
120 | |
121 // Callback passed to |filter_1_| during last Seek() call. | |
122 PipelineStatusCB filter_1_status_cb_; | |
123 | |
124 // Second filter added to the composite. | |
125 scoped_refptr<StrictMock<MockFilter> > filter_2_; | |
126 | |
127 // Callback passed to |filter_2_| during last Play(), Pause(), Flush(), | |
128 // Stop(), or Seek() call. | |
129 base::Closure filter_2_cb_; | |
130 | |
131 // Status to pass to |filter_2_status_cb_|. | |
132 PipelineStatus filter_2_status_; | |
133 | |
134 // Callback passed to |filter_2_| during last Seek() call. | |
135 PipelineStatusCB filter_2_status_cb_; | |
136 | |
137 // FilterHost implementation passed to |composite_| via SetHost(). | |
138 scoped_ptr<StrictMock<MockFilterHost> > mock_filter_host_; | |
139 | |
140 DISALLOW_COPY_AND_ASSIGN(CompositeFilterTest); | |
141 }; | |
142 | |
143 CompositeFilterTest::CompositeFilterTest() : | |
144 composite_(new CompositeFilter(message_loop_.message_loop_proxy())), | |
145 filter_1_status_(PIPELINE_OK), | |
146 filter_2_status_(PIPELINE_OK), | |
147 mock_filter_host_(new StrictMock<MockFilterHost>()) { | |
148 } | |
149 | |
150 CompositeFilterTest::~CompositeFilterTest() {} | |
151 | |
152 void CompositeFilterTest::SetupAndAdd2Filters() { | |
153 mock_filter_host_.reset(new StrictMock<MockFilterHost>()); | |
154 composite_ = new CompositeFilter(message_loop_.message_loop_proxy()); | |
155 composite_->SetHost(mock_filter_host_.get()); | |
156 | |
157 // Setup |filter_1_| and arrange for methods to set | |
158 // |filter_1_cb_| when they are called. | |
159 filter_1_ = new StrictMock<MockFilter>(); | |
160 filter_1_cb_.Reset(); | |
161 filter_1_status_ = PIPELINE_OK; | |
162 filter_1_status_cb_.Reset(); | |
163 ON_CALL(*filter_1_, Play(_)) | |
164 .WillByDefault(SaveArg<0>(&filter_1_cb_)); | |
165 ON_CALL(*filter_1_, Pause(_)) | |
166 .WillByDefault(SaveArg<0>(&filter_1_cb_)); | |
167 ON_CALL(*filter_1_, Flush(_)) | |
168 .WillByDefault(SaveArg<0>(&filter_1_cb_)); | |
169 ON_CALL(*filter_1_, Stop(_)) | |
170 .WillByDefault(SaveArg<0>(&filter_1_cb_)); | |
171 ON_CALL(*filter_1_, Seek(_,_)) | |
172 .WillByDefault(SaveArg<1>(&filter_1_status_cb_)); | |
173 | |
174 // Setup |filter_2_| and arrange for methods to set | |
175 // |filter_2_cb_| when they are called. | |
176 filter_2_ = new StrictMock<MockFilter>(); | |
177 filter_2_cb_.Reset(); | |
178 filter_2_status_ = PIPELINE_OK; | |
179 filter_2_status_cb_.Reset(); | |
180 ON_CALL(*filter_2_, Play(_)) | |
181 .WillByDefault(SaveArg<0>(&filter_2_cb_)); | |
182 ON_CALL(*filter_2_, Pause(_)) | |
183 .WillByDefault(SaveArg<0>(&filter_2_cb_)); | |
184 ON_CALL(*filter_2_, Flush(_)) | |
185 .WillByDefault(SaveArg<0>(&filter_2_cb_)); | |
186 ON_CALL(*filter_2_, Stop(_)) | |
187 .WillByDefault(SaveArg<0>(&filter_2_cb_)); | |
188 ON_CALL(*filter_2_, Seek(_,_)) | |
189 .WillByDefault(SaveArg<1>(&filter_2_status_cb_)); | |
190 | |
191 composite_->AddFilter(filter_1_); | |
192 composite_->AddFilter(filter_2_); | |
193 } | |
194 | |
195 void CompositeFilterTest::ExpectFilterCall(MethodToCall method_to_call, | |
196 MockFilter* filter, | |
197 base::TimeDelta seek_time) { | |
198 switch(method_to_call) { | |
199 case PLAY: | |
200 EXPECT_CALL(*filter, Play(_)); | |
201 break; | |
202 case PAUSE: | |
203 EXPECT_CALL(*filter, Pause(_)); | |
204 break; | |
205 case FLUSH: | |
206 EXPECT_CALL(*filter, Flush(_)); | |
207 break; | |
208 case STOP: | |
209 EXPECT_CALL(*filter, Stop(_)); | |
210 break; | |
211 case SEEK: | |
212 EXPECT_CALL(*filter, Seek(seek_time, _)); | |
213 break; | |
214 }; | |
215 } | |
216 | |
217 void OnStatusCB(PipelineStatus expected_status, const base::Closure& callback, | |
218 PipelineStatus status) { | |
219 EXPECT_EQ(status, expected_status); | |
220 callback.Run(); | |
221 } | |
222 | |
223 void CompositeFilterTest::DoFilterCall(MethodToCall method_to_call, | |
224 Filter* filter, | |
225 base::TimeDelta seek_time, | |
226 const base::Closure& callback, | |
227 PipelineStatus expected_status) { | |
228 filter_1_status_ = expected_status; | |
229 filter_2_status_ = expected_status; | |
230 | |
231 switch(method_to_call) { | |
232 case PLAY: | |
233 filter->Play(callback); | |
234 break; | |
235 case PAUSE: | |
236 filter->Pause(callback); | |
237 break; | |
238 case FLUSH: | |
239 filter->Flush(callback); | |
240 break; | |
241 case STOP: | |
242 filter->Stop(callback); | |
243 break; | |
244 case SEEK: | |
245 filter->Seek(seek_time, base::Bind(&OnStatusCB, expected_status, | |
246 callback)); | |
247 break; | |
248 }; | |
249 } | |
250 | |
251 void CompositeFilterTest::ExpectSuccess(MethodToCall method_to_call, | |
252 base::TimeDelta seek_time) { | |
253 InSequence seq; | |
254 | |
255 bool is_parallel_call = (method_to_call == FLUSH); | |
256 | |
257 ExpectFilterCall(method_to_call, filter_1_.get(), seek_time); | |
258 | |
259 if (is_parallel_call) { | |
260 ExpectFilterCall(method_to_call, filter_2_.get(), seek_time); | |
261 } | |
262 | |
263 // Make method call on the composite. | |
264 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
265 DoFilterCall(method_to_call, composite_.get(), seek_time, | |
266 base::Bind(&MockClosure::Run, callback), | |
267 PIPELINE_OK); | |
268 | |
269 if (is_parallel_call) { | |
270 // Make sure both filters have their callbacks set. | |
271 EXPECT_TRUE(HasFilter1Callback()); | |
272 EXPECT_TRUE(HasFilter2Callback()); | |
273 | |
274 RunFilter1Callback(); | |
275 } else { | |
276 // Make sure that only |filter_1_| has its callback set. | |
277 EXPECT_TRUE(HasFilter1Callback()); | |
278 EXPECT_FALSE(HasFilter2Callback()); | |
279 | |
280 ExpectFilterCall(method_to_call, filter_2_.get(), seek_time); | |
281 | |
282 RunFilter1Callback(); | |
283 | |
284 // Verify that |filter_2_| was called by checking the callback pointer. | |
285 EXPECT_TRUE(HasFilter2Callback()); | |
286 } | |
287 | |
288 EXPECT_CALL(*callback, Run()); | |
289 | |
290 RunFilter2Callback(); | |
291 } | |
292 | |
293 void CompositeFilterTest::DoPlay() { | |
294 ExpectSuccess(PLAY); | |
295 } | |
296 | |
297 void CompositeFilterTest::DoPause() { | |
298 ExpectSuccess(PAUSE); | |
299 } | |
300 | |
301 void CompositeFilterTest::DoFlush() { | |
302 ExpectSuccess(FLUSH); | |
303 } | |
304 | |
305 void CompositeFilterTest::DoStop() { | |
306 ExpectSuccess(STOP); | |
307 } | |
308 | |
309 void CompositeFilterTest::DoSeek(base::TimeDelta time) { | |
310 ExpectSuccess(SEEK, time); | |
311 } | |
312 | |
313 void CompositeFilterTest::ExpectInvalidStateFail(MethodToCall method_to_call, | |
314 base::TimeDelta seek_time) { | |
315 InSequence seq; | |
316 | |
317 if (method_to_call != SEEK) { | |
318 EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_INVALID_STATE)) | |
319 .WillOnce(Return()); | |
320 } | |
321 | |
322 DoFilterCall(method_to_call, composite_, seek_time, NewExpectedClosure(), | |
323 PIPELINE_ERROR_INVALID_STATE); | |
324 | |
325 // Make sure that neither of the filters were called by | |
326 // verifying that the callback pointers weren't set. | |
327 EXPECT_FALSE(HasFilter1Callback()); | |
328 EXPECT_FALSE(HasFilter2Callback()); | |
329 } | |
330 | |
331 bool CompositeFilterTest::HasFilter1Callback() const { | |
332 CHECK(filter_1_cb_.is_null() || filter_1_status_cb_.is_null()); | |
333 return !filter_1_cb_.is_null() || !filter_1_status_cb_.is_null(); | |
334 } | |
335 | |
336 void CompositeFilterTest::RunFilter1Callback() { | |
337 EXPECT_TRUE(HasFilter1Callback()); | |
338 | |
339 if (!filter_1_status_cb_.is_null()) { | |
340 base::ResetAndReturn(&filter_1_status_cb_).Run(filter_1_status_); | |
341 filter_1_status_ = PIPELINE_OK; | |
342 return; | |
343 } | |
344 | |
345 EXPECT_TRUE(!filter_1_cb_.is_null()); | |
346 base::Closure callback = filter_1_cb_; | |
347 filter_1_cb_.Reset(); | |
348 callback.Run(); | |
349 } | |
350 | |
351 bool CompositeFilterTest::HasFilter2Callback() const { | |
352 CHECK(filter_2_cb_.is_null() || filter_2_status_cb_.is_null()); | |
353 return !filter_2_cb_.is_null() || !filter_2_status_cb_.is_null(); | |
354 } | |
355 | |
356 void CompositeFilterTest::RunFilter2Callback() { | |
357 EXPECT_TRUE(HasFilter2Callback()); | |
358 | |
359 if (!filter_2_status_cb_.is_null()) { | |
360 base::ResetAndReturn(&filter_2_status_cb_).Run(filter_2_status_); | |
361 filter_2_status_ = PIPELINE_OK; | |
362 return; | |
363 } | |
364 | |
365 EXPECT_FALSE(filter_2_cb_.is_null()); | |
366 base::Closure callback = filter_2_cb_; | |
367 filter_2_cb_.Reset(); | |
368 callback.Run(); | |
369 } | |
370 | |
371 // Test successful AddFilter() cases. | |
372 TEST_F(CompositeFilterTest, TestAddFilter) { | |
373 composite_->SetHost(mock_filter_host_.get()); | |
374 | |
375 // Add a filter. | |
376 scoped_refptr<StrictMock<MockFilter> > filter = new StrictMock<MockFilter>(); | |
377 EXPECT_EQ(NULL, filter->host()); | |
378 | |
379 composite_->AddFilter(filter); | |
380 EXPECT_TRUE(filter->host() != NULL); | |
381 } | |
382 | |
383 class CompositeFilterDeathTest : public CompositeFilterTest { | |
384 public: | |
385 virtual void SetUp() { | |
386 // To avoid googletest warning in "fast" mode. | |
387 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | |
388 } | |
389 }; | |
390 | |
391 // Test AddFilter() failure cases. | |
392 TEST_F(CompositeFilterDeathTest, TestAddFilterFailCases) { | |
393 // Test adding a null pointer. | |
394 EXPECT_DEATH_IF_SUPPORTED(composite_->AddFilter(NULL), ""); | |
395 | |
396 scoped_refptr<StrictMock<MockFilter> > filter = new StrictMock<MockFilter>(); | |
397 EXPECT_EQ(NULL, filter->host()); | |
398 | |
399 // Test failing because SetHost() hasn't been called yet. | |
400 EXPECT_DEATH_IF_SUPPORTED(composite_->AddFilter(filter), ""); | |
401 } | |
402 | |
403 TEST_F(CompositeFilterTest, TestPlay) { | |
404 InSequence sequence; | |
405 | |
406 SetupAndAdd2Filters(); | |
407 | |
408 // Verify successful call to Play(). | |
409 DoPlay(); | |
410 | |
411 // At this point we are now in the kPlaying state. | |
412 | |
413 // Try calling Play() again to make sure that we simply get a callback. | |
414 // We are already in the Play() state so there is no point calling the | |
415 // filters. | |
416 composite_->Play(NewExpectedClosure()); | |
417 | |
418 // Verify that neither of the filter callbacks were set. | |
419 EXPECT_FALSE(HasFilter1Callback()); | |
420 EXPECT_FALSE(HasFilter2Callback()); | |
421 | |
422 // Stop playback. | |
423 DoStop(); | |
424 | |
425 // At this point we should be in the kStopped state. | |
426 | |
427 // Try calling Stop() again to make sure neither filter is called. | |
428 composite_->Stop(NewExpectedClosure()); | |
429 | |
430 // Verify that neither of the filter callbacks were set. | |
431 EXPECT_FALSE(HasFilter1Callback()); | |
432 EXPECT_FALSE(HasFilter2Callback()); | |
433 | |
434 // Try calling Play() again to make sure we get an error. | |
435 ExpectInvalidStateFail(PLAY); | |
436 } | |
437 | |
438 // Test errors in the middle of a serial call sequence like Play(). | |
439 TEST_F(CompositeFilterTest, TestPlayErrors) { | |
440 InSequence sequence; | |
441 | |
442 SetupAndAdd2Filters(); | |
443 | |
444 EXPECT_CALL(*filter_1_, Play(_)); | |
445 | |
446 // Call Play() on the composite. | |
447 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
448 composite_->Play(base::Bind(&MockClosure::Run, callback)); | |
449 | |
450 EXPECT_CALL(*filter_2_, Play(_)); | |
451 | |
452 // Run callback to indicate that |filter_1_|'s Play() has completed. | |
453 RunFilter1Callback(); | |
454 | |
455 // At this point Play() has been called on |filter_2_|. Simulate an | |
456 // error by calling SetError() on its FilterHost interface. | |
457 filter_2_->host()->SetError(PIPELINE_ERROR_DECODE); | |
458 | |
459 // Expect error to be reported and "play done" callback to be called. | |
460 EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); | |
461 EXPECT_CALL(*callback, Run()); | |
462 | |
463 // Run callback to indicate that |filter_2_|'s Play() has completed. | |
464 RunFilter2Callback(); | |
465 | |
466 // Verify that Play/Pause/Flush/Seek fail now that an error occured. | |
467 ExpectInvalidStateFail(PLAY); | |
468 ExpectInvalidStateFail(PAUSE); | |
469 ExpectInvalidStateFail(FLUSH); | |
470 ExpectInvalidStateFail(SEEK); | |
471 | |
472 // Make sure you can still Stop(). | |
473 DoStop(); | |
474 } | |
475 | |
476 TEST_F(CompositeFilterTest, TestPause) { | |
477 InSequence sequence; | |
478 | |
479 SetupAndAdd2Filters(); | |
480 | |
481 // Try calling Pause() to make sure we get an error because we aren't in | |
482 // the playing state. | |
483 ExpectInvalidStateFail(PAUSE); | |
484 | |
485 // Transition to playing state. | |
486 DoPlay(); | |
487 | |
488 // Issue a successful Pause(). | |
489 DoPause(); | |
490 | |
491 // At this point we are paused. | |
492 | |
493 // Try calling Pause() again to make sure that the filters aren't called | |
494 // because we are already in the paused state. | |
495 composite_->Pause(NewExpectedClosure()); | |
496 | |
497 // Verify that neither of the filter callbacks were set. | |
498 EXPECT_FALSE(HasFilter1Callback()); | |
499 EXPECT_FALSE(HasFilter2Callback()); | |
500 | |
501 // Verify that we can transition pack to the play state. | |
502 DoPlay(); | |
503 | |
504 // Go back to the pause state. | |
505 DoPause(); | |
506 | |
507 // Transition to the stop state. | |
508 DoStop(); | |
509 | |
510 // Try calling Pause() to make sure we get an error because we aren't in | |
511 // the playing state. | |
512 ExpectInvalidStateFail(PAUSE); | |
513 } | |
514 | |
515 // Test errors in the middle of a serial call sequence like Pause(). | |
516 TEST_F(CompositeFilterTest, TestPauseErrors) { | |
517 InSequence sequence; | |
518 | |
519 SetupAndAdd2Filters(); | |
520 | |
521 DoPlay(); | |
522 | |
523 EXPECT_CALL(*filter_1_, Pause(_)); | |
524 | |
525 // Call Pause() on the composite. | |
526 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
527 composite_->Pause(base::Bind(&MockClosure::Run, callback)); | |
528 | |
529 // Simulate an error by calling SetError() on |filter_1_|'s FilterHost | |
530 // interface. | |
531 filter_1_->host()->SetError(PIPELINE_ERROR_DECODE); | |
532 | |
533 // Expect error to be reported and "pause done" callback to be called. | |
534 EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); | |
535 EXPECT_CALL(*callback, Run()); | |
536 | |
537 RunFilter1Callback(); | |
538 | |
539 // Make sure |filter_2_cb_| was not set. | |
540 EXPECT_FALSE(HasFilter2Callback()); | |
541 | |
542 // Verify that Play/Pause/Flush/Seek fail now that an error occured. | |
543 ExpectInvalidStateFail(PLAY); | |
544 ExpectInvalidStateFail(PAUSE); | |
545 ExpectInvalidStateFail(FLUSH); | |
546 ExpectInvalidStateFail(SEEK); | |
547 | |
548 // Make sure you can still Stop(). | |
549 DoStop(); | |
550 } | |
551 | |
552 TEST_F(CompositeFilterTest, TestFlush) { | |
553 InSequence sequence; | |
554 | |
555 SetupAndAdd2Filters(); | |
556 | |
557 // Make sure Flush() works before calling Play(). | |
558 DoFlush(); | |
559 | |
560 // Transition to playing state. | |
561 DoPlay(); | |
562 | |
563 // Call Flush() to make sure we get an error because we are in | |
564 // the playing state. | |
565 ExpectInvalidStateFail(FLUSH); | |
566 | |
567 // Issue a successful Pause(). | |
568 DoPause(); | |
569 | |
570 // Make sure Flush() works after pausing. | |
571 DoFlush(); | |
572 | |
573 // Verify that we can transition back to the play state. | |
574 DoPlay(); | |
575 | |
576 // Transition to the stop state. | |
577 DoStop(); | |
578 | |
579 // Try calling Flush() to make sure we get an error because we are stopped. | |
580 ExpectInvalidStateFail(FLUSH); | |
581 } | |
582 | |
583 // Test errors in the middle of a parallel call sequence like Flush(). | |
584 TEST_F(CompositeFilterTest, TestFlushErrors) { | |
585 InSequence sequence; | |
586 | |
587 SetupAndAdd2Filters(); | |
588 | |
589 EXPECT_CALL(*filter_1_, Flush(_)); | |
590 EXPECT_CALL(*filter_2_, Flush(_)); | |
591 | |
592 // Call Flush() on the composite. | |
593 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
594 composite_->Flush(base::Bind(&MockClosure::Run, callback)); | |
595 | |
596 // Simulate an error by calling SetError() on |filter_1_|'s FilterHost | |
597 // interface. | |
598 filter_1_->host()->SetError(PIPELINE_ERROR_DECODE); | |
599 | |
600 RunFilter1Callback(); | |
601 | |
602 // Expect error to be reported and "pause done" callback to be called. | |
603 EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); | |
604 EXPECT_CALL(*callback, Run()); | |
605 | |
606 RunFilter2Callback(); | |
607 | |
608 // Verify that Play/Pause/Flush/Seek fail now that an error occured. | |
609 ExpectInvalidStateFail(PLAY); | |
610 ExpectInvalidStateFail(PAUSE); | |
611 ExpectInvalidStateFail(FLUSH); | |
612 ExpectInvalidStateFail(SEEK); | |
613 | |
614 // Make sure you can still Stop(). | |
615 DoStop(); | |
616 } | |
617 | |
618 TEST_F(CompositeFilterTest, TestSeek) { | |
619 InSequence sequence; | |
620 | |
621 SetupAndAdd2Filters(); | |
622 | |
623 // Verify that seek is allowed to be called before a Play() call. | |
624 DoSeek(base::TimeDelta::FromSeconds(5)); | |
625 | |
626 // Verify we can issue a Play() after the Seek(). | |
627 DoPlay(); | |
628 | |
629 // Try calling Seek() while playing to make sure we get an error. | |
630 ExpectInvalidStateFail(SEEK); | |
631 | |
632 // Transition to paused state. | |
633 DoPause(); | |
634 | |
635 // Verify that seek is allowed after pausing. | |
636 DoSeek(base::TimeDelta::FromSeconds(5)); | |
637 | |
638 // Verify we can still play again. | |
639 DoPlay(); | |
640 | |
641 // Stop playback. | |
642 DoStop(); | |
643 | |
644 // Try calling Seek() to make sure we get an error. | |
645 ExpectInvalidStateFail(SEEK); | |
646 } | |
647 | |
648 TEST_F(CompositeFilterTest, TestStop) { | |
649 InSequence sequence; | |
650 | |
651 // Test Stop() before any other call. | |
652 SetupAndAdd2Filters(); | |
653 DoStop(); | |
654 | |
655 // Test error during Stop() sequence. | |
656 SetupAndAdd2Filters(); | |
657 | |
658 EXPECT_CALL(*filter_1_, Stop(_)); | |
659 | |
660 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
661 composite_->Stop(base::Bind(&MockClosure::Run, callback)); | |
662 | |
663 // Have |filter_1_| signal an error. | |
664 filter_1_->host()->SetError(PIPELINE_ERROR_READ); | |
665 | |
666 EXPECT_CALL(*filter_2_, Stop(_)); | |
667 | |
668 RunFilter1Callback(); | |
669 | |
670 EXPECT_CALL(*callback, Run()); | |
671 | |
672 RunFilter2Callback(); | |
673 } | |
674 | |
675 // Test stopping in the middle of a serial call sequence. | |
676 TEST_F(CompositeFilterTest, TestStopWhilePlayPending) { | |
677 InSequence sequence; | |
678 | |
679 SetupAndAdd2Filters(); | |
680 | |
681 EXPECT_CALL(*filter_1_, Play(_)); | |
682 | |
683 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
684 composite_->Play(base::Bind(&MockClosure::Run, callback)); | |
685 | |
686 // Note: Play() is pending on |filter_1_| right now. | |
687 | |
688 callback = new StrictMock<MockClosure>(); | |
689 composite_->Stop(base::Bind(&MockClosure::Run, callback)); | |
690 | |
691 EXPECT_CALL(*filter_1_, Stop(_)); | |
692 | |
693 // Run |filter_1_|'s callback again to indicate Play() has completed. | |
694 RunFilter1Callback(); | |
695 | |
696 EXPECT_CALL(*filter_2_, Stop(_)); | |
697 | |
698 // Run |filter_1_|'s callback again to indicate Stop() has completed. | |
699 RunFilter1Callback(); | |
700 | |
701 EXPECT_CALL(*callback, Run()); | |
702 | |
703 // Run |filter_2_|'s callback to indicate Stop() has completed. | |
704 RunFilter2Callback(); | |
705 } | |
706 | |
707 // Test stopping in the middle of a parallel call sequence. | |
708 TEST_F(CompositeFilterTest, TestStopWhileFlushPending) { | |
709 InSequence sequence; | |
710 | |
711 SetupAndAdd2Filters(); | |
712 | |
713 EXPECT_CALL(*filter_1_, Flush(_)); | |
714 EXPECT_CALL(*filter_2_, Flush(_)); | |
715 | |
716 StrictMock<MockClosure>* callback = new StrictMock<MockClosure>(); | |
717 composite_->Flush(base::Bind(&MockClosure::Run, callback)); | |
718 | |
719 // Note: |filter_1_| and |filter_2_| have pending Flush() calls at this point. | |
720 | |
721 callback = new StrictMock<MockClosure>(); | |
722 composite_->Stop(base::Bind(&MockClosure::Run, callback)); | |
723 | |
724 // Run callback to indicate that |filter_1_|'s Flush() has completed. | |
725 RunFilter1Callback(); | |
726 | |
727 EXPECT_CALL(*filter_1_, Stop(_)); | |
728 | |
729 // Run callback to indicate that |filter_2_|'s Flush() has completed. | |
730 RunFilter2Callback(); | |
731 | |
732 EXPECT_CALL(*filter_2_, Stop(_)); | |
733 | |
734 // Run callback to indicate that |filter_1_|'s Stop() has completed. | |
735 RunFilter1Callback(); | |
736 | |
737 EXPECT_CALL(*callback, Run()); | |
738 | |
739 // Run callback to indicate that |filter_2_|'s Stop() has completed. | |
740 RunFilter2Callback(); | |
741 } | |
742 | |
743 TEST_F(CompositeFilterTest, TestErrorWhilePlaying) { | |
744 InSequence sequence; | |
745 | |
746 SetupAndAdd2Filters(); | |
747 | |
748 DoPlay(); | |
749 | |
750 // Simulate an error on |filter_2_| while playing. | |
751 EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); | |
752 filter_2_->host()->SetError(PIPELINE_ERROR_DECODE); | |
753 | |
754 DoPause(); | |
755 | |
756 // Simulate an error on |filter_2_| while paused. | |
757 EXPECT_CALL(*mock_filter_host_, SetError(PIPELINE_ERROR_NETWORK)); | |
758 filter_2_->host()->SetError(PIPELINE_ERROR_NETWORK); | |
759 | |
760 DoStop(); | |
761 | |
762 // Verify that errors are not passed to |mock_filter_host_| | |
763 // after Stop() has been called. | |
764 filter_2_->host()->SetError(PIPELINE_ERROR_NETWORK); | |
765 } | |
766 | |
767 // Make sure that state transitions act as expected even | |
768 // if the composite doesn't contain any filters. | |
769 TEST_F(CompositeFilterTest, TestEmptyComposite) { | |
770 InSequence sequence; | |
771 | |
772 composite_->SetHost(mock_filter_host_.get()); | |
773 | |
774 // Issue a Play() and expect no errors. | |
775 composite_->Play(NewExpectedClosure()); | |
776 | |
777 // Issue a Pause() and expect no errors. | |
778 composite_->Pause(NewExpectedClosure()); | |
779 | |
780 // Issue a Flush() and expect no errors. | |
781 composite_->Flush(NewExpectedClosure()); | |
782 | |
783 // Issue a Seek() and expect no errors. | |
784 composite_->Seek(base::TimeDelta::FromSeconds(5), | |
785 NewExpectedStatusCB(PIPELINE_OK)); | |
786 | |
787 // Issue a Play() and expect no errors. | |
788 composite_->Play(NewExpectedClosure()); | |
789 | |
790 // Issue a Stop() and expect no errors. | |
791 composite_->Stop(NewExpectedClosure()); | |
792 } | |
793 | |
794 } // namespace media | |
OLD | NEW |