Chromium Code Reviews| Index: media/filters/ffmpeg_demuxer_unittest.cc |
| diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc |
| index 0622e017477be5cdd143a339d31ea0d1e91cbcd2..1d51de33e7cc88d45c1575c5b23cd1a767c90abb 100644 |
| --- a/media/filters/ffmpeg_demuxer_unittest.cc |
| +++ b/media/filters/ffmpeg_demuxer_unittest.cc |
| @@ -31,6 +31,11 @@ using ::testing::_; |
| namespace media { |
| +MATCHER(IsEndOfStreamBuffer, |
| + std::string(negation ? "isn't" : "is") + " end of stream") { |
| + return arg->IsEndOfStream(); |
| +} |
| + |
| // Fixture class to facilitate writing tests. Takes care of setting up the |
| // FFmpeg, pipeline and filter host mocks. |
| class FFmpegDemuxerTest : public testing::Test { |
| @@ -51,8 +56,9 @@ class FFmpegDemuxerTest : public testing::Test { |
| } |
| virtual ~FFmpegDemuxerTest() { |
| - // Call Stop() to shut down internal threads. |
| - demuxer_->Stop(NewExpectedClosure()); |
| + if (demuxer_) |
|
scherkus (not reviewing)
2011/10/15 01:32:14
could you add {} around here
ddorwin
2011/10/15 01:38:16
Done.
|
| + // Call Stop() to shut down internal threads. |
| + demuxer_->Stop(NewExpectedClosure()); |
| // Finish up any remaining tasks. |
| message_loop_.RunAllPending(); |
| @@ -376,8 +382,8 @@ class MockReadCallback : public base::RefCountedThreadSafe<MockReadCallback> { |
| }; |
| TEST_F(FFmpegDemuxerTest, Stop) { |
| - // Tests that calling Read() on a stopped demuxer immediately deletes the |
| - // callback. |
| + // Tests that calling Read() on a stopped demuxer stream immediately deletes |
| + // the callback. |
| InitializeDemuxer(CreateDataSource("bear-320x240.webm")); |
| // Get our stream. |
| @@ -396,6 +402,7 @@ TEST_F(FFmpegDemuxerTest, Stop) { |
| // The callback should be immediately deleted. We'll use a checkpoint to |
| // verify that it has indeed been deleted. |
| + EXPECT_CALL(*callback, Run(NotNull())); |
| EXPECT_CALL(*callback, OnDelete()); |
| EXPECT_CALL(*this, CheckPoint(1)); |
| @@ -408,6 +415,49 @@ TEST_F(FFmpegDemuxerTest, Stop) { |
| CheckPoint(1); |
| } |
| +// The streams can outlive the demuxer because the streams may still be in use |
| +// by the decoder when the demuxer is destroyed. |
| +// This test verifies that DemuxerStream::Read() does not use an invalid demuxer |
| +// pointer (no crash occurs) and calls the callback with an EndOfStream buffer. |
| +TEST_F(FFmpegDemuxerTest, StreamReadAfterStopAndDemuxerDestruction) { |
| + InitializeDemuxer(CreateDataSource("bear-320x240.webm")); |
| + |
| + // Get our stream. |
| + scoped_refptr<DemuxerStream> audio = |
| + demuxer_->GetStream(DemuxerStream::AUDIO); |
| + ASSERT_TRUE(audio); |
| + |
| + demuxer_->Stop(NewExpectedClosure()); |
| + |
| + // Finish up any remaining tasks. |
| + message_loop_.RunAllPending(); |
| + |
| + // Expect all calls in sequence. |
| + InSequence s; |
| + |
| + // Create our mocked callback. The Callback created by base::Bind() will take |
| + // ownership of this pointer. |
| + StrictMock<MockReadCallback>* callback = new StrictMock<MockReadCallback>(); |
| + |
| + // The callback should be immediately deleted. We'll use a checkpoint to |
| + // verify that it has indeed been deleted. |
| + EXPECT_CALL(*callback, Run(IsEndOfStreamBuffer())); |
| + EXPECT_CALL(*callback, OnDelete()); |
| + EXPECT_CALL(*this, CheckPoint(1)); |
| + |
| + // Release the reference to the demuxer. This should also destroy it. |
| + demuxer_ = NULL; |
| + // |audio| now has a demuxer_ pointer to invalid memory. |
| + |
| + // Attempt the read... |
| + audio->Read(base::Bind(&MockReadCallback::Run, callback)); |
| + |
| + message_loop_.RunAllPending(); |
| + |
| + // ...and verify that |callback| was deleted. |
| + CheckPoint(1); |
| +} |
| + |
| TEST_F(FFmpegDemuxerTest, DisableAudioStream) { |
| // We are doing the following things here: |
| // 1. Initialize the demuxer with audio and video stream. |