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