| 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 |