Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: media/base/pipeline_unittest.cc

Issue 10832197: Add a lot of Pipeline tests to cover stopping/error handling while in a variety of states. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/base/pipeline.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/threading/simple_thread.h" 10 #include "base/threading/simple_thread.h"
11 #include "media/base/clock.h" 11 #include "media/base/clock.h"
12 #include "media/base/media_log.h" 12 #include "media/base/media_log.h"
13 #include "media/base/pipeline.h" 13 #include "media/base/pipeline.h"
14 #include "media/base/mock_callback.h" 14 #include "media/base/mock_callback.h"
15 #include "media/base/mock_filters.h" 15 #include "media/base/mock_filters.h"
16 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
18 18
19 using ::testing::_; 19 using ::testing::_;
20 using ::testing::DeleteArg; 20 using ::testing::DeleteArg;
21 using ::testing::DoAll; 21 using ::testing::DoAll;
22 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
22 using ::testing::InSequence; 23 using ::testing::InSequence;
23 using ::testing::Invoke; 24 using ::testing::Invoke;
24 using ::testing::InvokeWithoutArgs; 25 using ::testing::InvokeWithoutArgs;
25 using ::testing::Mock; 26 using ::testing::Mock;
26 using ::testing::NotNull; 27 using ::testing::NotNull;
27 using ::testing::Return; 28 using ::testing::Return;
28 using ::testing::ReturnRef; 29 using ::testing::ReturnRef;
29 using ::testing::SaveArg; 30 using ::testing::SaveArg;
30 using ::testing::StrictMock; 31 using ::testing::StrictMock;
31 using ::testing::WithArg; 32 using ::testing::WithArg;
32 33
33 namespace media { 34 namespace media {
34 35
35 // Demuxer properties. 36 // Demuxer properties.
36 static const int kTotalBytes = 1024; 37 static const int kTotalBytes = 1024;
37 static const int kBitrate = 1234; 38 static const int kBitrate = 1234;
38 39
39 ACTION_P(SetDemuxerProperties, duration) { 40 ACTION_P(SetDemuxerProperties, duration) {
40 arg0->SetTotalBytes(kTotalBytes); 41 arg0->SetTotalBytes(kTotalBytes);
41 arg0->SetDuration(duration); 42 arg0->SetDuration(duration);
42 } 43 }
43 44
44 ACTION(RunPipelineStatusCB1) { 45 ACTION_P2(Stop, pipeline, stop_cb) {
46 pipeline->Stop(stop_cb);
47 }
48
49 ACTION_P2(SetError, pipeline, status) {
50 pipeline->SetErrorForTesting(status);
51 }
52
53 ACTION(RunPipelineStatusCB) {
45 arg1.Run(PIPELINE_OK); 54 arg1.Run(PIPELINE_OK);
46 } 55 }
47 56
48 ACTION_P(RunPipelineStatusCB1WithStatus, status) { 57 ACTION_P(RunPipelineStatusCBWithStatus, status) {
49 arg1.Run(status); 58 arg1.Run(status);
50 } 59 }
51 60
52 // Used for setting expectations on pipeline callbacks. Using a StrictMock 61 // Used for setting expectations on pipeline callbacks. Using a StrictMock
53 // also lets us test for missing callbacks. 62 // also lets us test for missing callbacks.
54 class CallbackHelper { 63 class CallbackHelper {
55 public: 64 public:
56 CallbackHelper() {} 65 CallbackHelper() {}
57 virtual ~CallbackHelper() {} 66 virtual ~CallbackHelper() {}
58 67
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 virtual ~PipelineTest() { 100 virtual ~PipelineTest() {
92 if (!pipeline_->IsRunning()) { 101 if (!pipeline_->IsRunning()) {
93 return; 102 return;
94 } 103 }
95 104
96 // Shutdown sequence. 105 // Shutdown sequence.
97 if (pipeline_->IsInitialized()) { 106 if (pipeline_->IsInitialized()) {
98 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) 107 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
99 .WillOnce(RunClosure()); 108 .WillOnce(RunClosure());
100 109
110 // TODO(scherkus): Don't pause+flush on shutdown,
111 // see http://crbug.com/110228
101 if (audio_stream_) { 112 if (audio_stream_) {
102 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) 113 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
103 .WillOnce(RunClosure()); 114 .WillOnce(RunClosure());
104 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) 115 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
105 .WillOnce(RunClosure()); 116 .WillOnce(RunClosure());
106 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) 117 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_))
107 .WillOnce(RunClosure()); 118 .WillOnce(RunClosure());
108 } 119 }
109 120
110 if (video_stream_) { 121 if (video_stream_) {
(...skipping 16 matching lines...) Expand all
127 mocks_.reset(); 138 mocks_.reset();
128 } 139 }
129 140
130 protected: 141 protected:
131 // Sets up expectations to allow the demuxer to initialize. 142 // Sets up expectations to allow the demuxer to initialize.
132 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; 143 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
133 void InitializeDemuxer(MockDemuxerStreamVector* streams, 144 void InitializeDemuxer(MockDemuxerStreamVector* streams,
134 const base::TimeDelta& duration) { 145 const base::TimeDelta& duration) {
135 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) 146 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _))
136 .WillOnce(DoAll(SetDemuxerProperties(duration), 147 .WillOnce(DoAll(SetDemuxerProperties(duration),
137 RunPipelineStatusCB1())); 148 RunPipelineStatusCB()));
138 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f)); 149 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f));
139 150
140 // Configure the demuxer to return the streams. 151 // Configure the demuxer to return the streams.
141 for (size_t i = 0; i < streams->size(); ++i) { 152 for (size_t i = 0; i < streams->size(); ++i) {
142 scoped_refptr<DemuxerStream> stream((*streams)[i]); 153 scoped_refptr<DemuxerStream> stream((*streams)[i]);
143 EXPECT_CALL(*mocks_->demuxer(), GetStream(stream->type())) 154 EXPECT_CALL(*mocks_->demuxer(), GetStream(stream->type()))
144 .WillRepeatedly(Return(stream)); 155 .WillRepeatedly(Return(stream));
145 } 156 }
146 } 157 }
147 158
148 void InitializeDemuxer(MockDemuxerStreamVector* streams) { 159 void InitializeDemuxer(MockDemuxerStreamVector* streams) {
149 // Initialize with a default non-zero duration. 160 // Initialize with a default non-zero duration.
150 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10)); 161 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10));
151 } 162 }
152 163
153 StrictMock<MockDemuxerStream>* CreateStream(DemuxerStream::Type type) { 164 StrictMock<MockDemuxerStream>* CreateStream(DemuxerStream::Type type) {
154 StrictMock<MockDemuxerStream>* stream = 165 StrictMock<MockDemuxerStream>* stream =
155 new StrictMock<MockDemuxerStream>(); 166 new StrictMock<MockDemuxerStream>();
156 EXPECT_CALL(*stream, type()) 167 EXPECT_CALL(*stream, type())
157 .WillRepeatedly(Return(type)); 168 .WillRepeatedly(Return(type));
158 return stream; 169 return stream;
159 } 170 }
160 171
161 // Sets up expectations to allow the video decoder to initialize. 172 // Sets up expectations to allow the video decoder to initialize.
162 void InitializeVideoDecoder(const scoped_refptr<DemuxerStream>& stream) { 173 void InitializeVideoDecoder(const scoped_refptr<DemuxerStream>& stream) {
163 EXPECT_CALL(*mocks_->video_decoder(), 174 EXPECT_CALL(*mocks_->video_decoder(),
164 Initialize(stream, _, _)) 175 Initialize(stream, _, _))
165 .WillOnce(RunPipelineStatusCB1()); 176 .WillOnce(RunPipelineStatusCB());
166 } 177 }
167 178
168 // Sets up expectations to allow the audio decoder to initialize. 179 // Sets up expectations to allow the audio decoder to initialize.
169 void InitializeAudioDecoder(const scoped_refptr<DemuxerStream>& stream) { 180 void InitializeAudioDecoder(const scoped_refptr<DemuxerStream>& stream) {
170 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, _, _)) 181 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, _, _))
171 .WillOnce(RunPipelineStatusCB1()); 182 .WillOnce(RunPipelineStatusCB());
172 } 183 }
173 184
174 // Sets up expectations to allow the video renderer to initialize. 185 // Sets up expectations to allow the video renderer to initialize.
175 void InitializeVideoRenderer() { 186 void InitializeVideoRenderer() {
176 EXPECT_CALL(*mocks_->video_renderer(), Initialize( 187 EXPECT_CALL(*mocks_->video_renderer(), Initialize(
177 scoped_refptr<VideoDecoder>(mocks_->video_decoder()), 188 scoped_refptr<VideoDecoder>(mocks_->video_decoder()),
178 _, _, _, _, _, _, _, _)) 189 _, _, _, _, _, _, _, _))
179 .WillOnce(RunPipelineStatusCB1()); 190 .WillOnce(RunPipelineStatusCB());
180 EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f)); 191 EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f));
181 192
182 // Startup sequence. 193 // Startup sequence.
183 EXPECT_CALL(*mocks_->video_renderer(), 194 EXPECT_CALL(*mocks_->video_renderer(),
184 Preroll(mocks_->demuxer()->GetStartTime(), _)) 195 Preroll(mocks_->demuxer()->GetStartTime(), _))
185 .WillOnce(RunPipelineStatusCB1()); 196 .WillOnce(RunPipelineStatusCB());
186 EXPECT_CALL(*mocks_->video_renderer(), Play(_)) 197 EXPECT_CALL(*mocks_->video_renderer(), Play(_))
187 .WillOnce(RunClosure()); 198 .WillOnce(RunClosure());
188 } 199 }
189 200
190 // Sets up expectations to allow the audio renderer to initialize. 201 // Sets up expectations to allow the audio renderer to initialize.
191 void InitializeAudioRenderer(bool disable_after_init_cb = false) { 202 void InitializeAudioRenderer(bool disable_after_init_cb = false) {
192 if (disable_after_init_cb) { 203 if (disable_after_init_cb) {
193 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( 204 EXPECT_CALL(*mocks_->audio_renderer(), Initialize(
194 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), 205 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()),
195 _, _, _, _, _, _)) 206 _, _, _, _, _, _))
196 .WillOnce(DoAll(RunPipelineStatusCB1(), 207 .WillOnce(DoAll(RunPipelineStatusCB(),
197 WithArg<5>(RunClosure()))); // |disabled_cb|. 208 WithArg<5>(RunClosure()))); // |disabled_cb|.
198 } else { 209 } else {
199 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( 210 EXPECT_CALL(*mocks_->audio_renderer(), Initialize(
200 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), 211 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()),
201 _, _, _, _, _, _)) 212 _, _, _, _, _, _))
202 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_), 213 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_),
203 RunPipelineStatusCB1())); 214 RunPipelineStatusCB()));
204 } 215 }
205 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f)); 216 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f));
206 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f)); 217 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f));
207 218
208 // Startup sequence. 219 // Startup sequence.
209 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(base::TimeDelta(), _)) 220 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(base::TimeDelta(), _))
210 .WillOnce(RunPipelineStatusCB1()); 221 .WillOnce(RunPipelineStatusCB());
211 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) 222 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
212 .WillOnce(RunClosure()); 223 .WillOnce(RunClosure());
213 } 224 }
214 225
215 // Sets up expectations on the callback and initializes the pipeline. Called 226 // Sets up expectations on the callback and initializes the pipeline. Called
216 // after tests have set expectations any filters they wish to use. 227 // after tests have set expectations any filters they wish to use.
217 void InitializePipeline(PipelineStatus start_status) { 228 void InitializePipeline(PipelineStatus start_status) {
218 EXPECT_CALL(callbacks_, OnStart(start_status)); 229 EXPECT_CALL(callbacks_, OnStart(start_status));
219 230
220 pipeline_->Start( 231 pipeline_->Start(
(...skipping 16 matching lines...) Expand all
237 return audio_stream_; 248 return audio_stream_;
238 } 249 }
239 250
240 MockDemuxerStream* video_stream() { 251 MockDemuxerStream* video_stream() {
241 return video_stream_; 252 return video_stream_;
242 } 253 }
243 254
244 void ExpectSeek(const base::TimeDelta& seek_time) { 255 void ExpectSeek(const base::TimeDelta& seek_time) {
245 // Every filter should receive a call to Seek(). 256 // Every filter should receive a call to Seek().
246 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) 257 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _))
247 .WillOnce(RunPipelineStatusCB1()); 258 .WillOnce(RunPipelineStatusCB());
248 259
249 if (audio_stream_) { 260 if (audio_stream_) {
250 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) 261 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
251 .WillOnce(RunClosure()); 262 .WillOnce(RunClosure());
252 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) 263 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
253 .WillOnce(RunClosure()); 264 .WillOnce(RunClosure());
254 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _)) 265 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _))
255 .WillOnce(RunPipelineStatusCB1()); 266 .WillOnce(RunPipelineStatusCB());
256 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) 267 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
257 .WillOnce(RunClosure()); 268 .WillOnce(RunClosure());
258 } 269 }
259 270
260 if (video_stream_) { 271 if (video_stream_) {
261 EXPECT_CALL(*mocks_->video_renderer(), Pause(_)) 272 EXPECT_CALL(*mocks_->video_renderer(), Pause(_))
262 .WillOnce(RunClosure()); 273 .WillOnce(RunClosure());
263 EXPECT_CALL(*mocks_->video_renderer(), Flush(_)) 274 EXPECT_CALL(*mocks_->video_renderer(), Flush(_))
264 .WillOnce(RunClosure()); 275 .WillOnce(RunClosure());
265 EXPECT_CALL(*mocks_->video_renderer(), Preroll(seek_time, _)) 276 EXPECT_CALL(*mocks_->video_renderer(), Preroll(seek_time, _))
266 .WillOnce(RunPipelineStatusCB1()); 277 .WillOnce(RunPipelineStatusCB());
267 EXPECT_CALL(*mocks_->video_renderer(), Play(_)) 278 EXPECT_CALL(*mocks_->video_renderer(), Play(_))
268 .WillOnce(RunClosure()); 279 .WillOnce(RunClosure());
269 } 280 }
270 281
271 // We expect a successful seek callback. 282 // We expect a successful seek callback.
272 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); 283 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
273 } 284 }
274 285
275 void DoSeek(const base::TimeDelta& seek_time) { 286 void DoSeek(const base::TimeDelta& seek_time) {
276 pipeline_->Seek(seek_time, 287 pipeline_->Seek(seek_time,
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 collection.Pass(), 379 collection.Pass(),
369 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), 380 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
370 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), 381 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
371 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); 382 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)));
372 message_loop_.RunAllPending(); 383 message_loop_.RunAllPending();
373 EXPECT_FALSE(pipeline_->IsInitialized()); 384 EXPECT_FALSE(pipeline_->IsInitialized());
374 } 385 }
375 386
376 TEST_F(PipelineTest, URLNotFound) { 387 TEST_F(PipelineTest, URLNotFound) {
377 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) 388 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _))
378 .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_URL_NOT_FOUND)); 389 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_URL_NOT_FOUND));
379 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) 390 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
380 .WillOnce(RunClosure()); 391 .WillOnce(RunClosure());
381 392
382 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND); 393 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
383 EXPECT_FALSE(pipeline_->IsInitialized()); 394 EXPECT_FALSE(pipeline_->IsInitialized());
384 } 395 }
385 396
386 TEST_F(PipelineTest, NoStreams) { 397 TEST_F(PipelineTest, NoStreams) {
387 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) 398 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _))
388 .WillOnce(RunPipelineStatusCB1()); 399 .WillOnce(RunPipelineStatusCB());
389 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) 400 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
390 .WillOnce(RunClosure()); 401 .WillOnce(RunClosure());
391 402
392 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER); 403 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
393 EXPECT_FALSE(pipeline_->IsInitialized()); 404 EXPECT_FALSE(pipeline_->IsInitialized());
394 } 405 }
395 406
396 TEST_F(PipelineTest, AudioStream) { 407 TEST_F(PipelineTest, AudioStream) {
397 CreateAudioStream(); 408 CreateAudioStream();
398 MockDemuxerStreamVector streams; 409 MockDemuxerStreamVector streams;
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 741
731 // Seek() isn't called as the demuxer errors out first. 742 // Seek() isn't called as the demuxer errors out first.
732 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) 743 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
733 .WillOnce(RunClosure()); 744 .WillOnce(RunClosure());
734 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) 745 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
735 .WillOnce(RunClosure()); 746 .WillOnce(RunClosure());
736 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) 747 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_))
737 .WillOnce(RunClosure()); 748 .WillOnce(RunClosure());
738 749
739 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) 750 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _))
740 .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_READ)); 751 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ));
741 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) 752 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
742 .WillOnce(RunClosure()); 753 .WillOnce(RunClosure());
743 754
744 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, 755 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
745 base::Unretained(&callbacks_))); 756 base::Unretained(&callbacks_)));
746 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); 757 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
747 message_loop_.RunAllPending(); 758 message_loop_.RunAllPending();
748 } 759 }
749 760
750 // Invoked function OnError. This asserts that the pipeline does not enqueue 761 // Invoked function OnError. This asserts that the pipeline does not enqueue
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 797
787 // Seek() isn't called as the demuxer errors out first. 798 // Seek() isn't called as the demuxer errors out first.
788 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) 799 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
789 .WillOnce(RunClosure()); 800 .WillOnce(RunClosure());
790 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) 801 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
791 .WillOnce(RunClosure()); 802 .WillOnce(RunClosure());
792 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) 803 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_))
793 .WillOnce(RunClosure()); 804 .WillOnce(RunClosure());
794 805
795 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) 806 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _))
796 .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_READ)); 807 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ));
797 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) 808 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
798 .WillOnce(RunClosure()); 809 .WillOnce(RunClosure());
799 810
800 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, 811 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
801 base::Unretained(&callbacks_))); 812 base::Unretained(&callbacks_)));
802 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); 813 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
803 message_loop_.RunAllPending(); 814 message_loop_.RunAllPending();
804 } 815 }
805 816
806 TEST_F(PipelineTest, StartTimeIsZero) { 817 TEST_F(PipelineTest, StartTimeIsZero) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 base::TimeDelta::FromMilliseconds(500)); 884 base::TimeDelta::FromMilliseconds(500));
874 885
875 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); 886 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
876 887
877 // Arrange to trigger a time update while the demuxer is in the middle of 888 // Arrange to trigger a time update while the demuxer is in the middle of
878 // seeking. This update should be ignored by the pipeline and the clock should 889 // seeking. This update should be ignored by the pipeline and the clock should
879 // not get updated. 890 // not get updated.
880 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700); 891 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
881 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) 892 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _))
882 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run), 893 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
883 RunPipelineStatusCB1())); 894 RunPipelineStatusCB()));
884 895
885 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) 896 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
886 .WillOnce(RunClosure()); 897 .WillOnce(RunClosure());
887 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) 898 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
888 .WillOnce(RunClosure()); 899 .WillOnce(RunClosure());
889 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _)) 900 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _))
890 .WillOnce(RunPipelineStatusCB1()); 901 .WillOnce(RunPipelineStatusCB());
891 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) 902 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
892 .WillOnce(RunClosure()); 903 .WillOnce(RunClosure());
893 904
894 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); 905 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
895 DoSeek(seek_time); 906 DoSeek(seek_time);
896 907
897 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time); 908 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
898 909
899 // Now that the seek is complete, verify that time updates advance the current 910 // Now that the seek is complete, verify that time updates advance the current
900 // time. 911 // time.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 TEST(PipelineStatusNotificationTest, ImmediateCallback) { 961 TEST(PipelineStatusNotificationTest, ImmediateCallback) {
951 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(0)); 962 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(0));
952 } 963 }
953 964
954 // Test that different-thread, some-delay callback (the expected common case) 965 // Test that different-thread, some-delay callback (the expected common case)
955 // works correctly. 966 // works correctly.
956 TEST(PipelineStatusNotificationTest, DelayedCallback) { 967 TEST(PipelineStatusNotificationTest, DelayedCallback) {
957 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(20)); 968 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(20));
958 } 969 }
959 970
971 class PipelineTeardownTest : public PipelineTest {
972 public:
973 enum TeardownState {
974 kPausing,
975 kFlushing,
976 kSeeking,
977 kPrerolling,
978 kStarting,
979 kPlaying,
980 };
981
982 enum StopOrError {
983 kStop,
984 kError,
985 };
986
987 PipelineTeardownTest() {
988 CreateAudioStream();
989 MockDemuxerStreamVector streams;
990 streams.push_back(audio_stream());
991
992 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
993 InitializeAudioDecoder(audio_stream());
994 InitializeAudioRenderer();
995 InitializePipeline(PIPELINE_OK);
996 }
997
998 void RunTest(TeardownState state, StopOrError stop_or_error) {
999 InSequence s;
1000 switch (state) {
1001 case kPausing:
1002 case kFlushing:
1003 case kSeeking:
1004 case kPrerolling:
1005 case kStarting:
1006 if (stop_or_error == kStop) {
1007 ExpectSeekStop(state);
1008 } else {
1009 ExpectSeekError(state);
1010 }
1011 DoSeek();
1012 break;
1013
1014 case kPlaying:
1015 if (stop_or_error == kStop) {
1016 ExpectStop();
1017 DoStop();
1018 } else {
1019 ExpectPlaybackError();
1020 DoPlaybackError();
1021 }
1022 break;
1023 }
1024 }
1025
1026 private:
1027 // TODO(scherkus): Why separate stop/error enums and helper functions? We do
Ami GONE FROM CHROMIUM 2012/08/09 04:41:43 rewrite comment.
scherkus (not reviewing) 2012/08/09 16:52:39 Done.
1028 // radically different things whether teardown is invoked via stop vs error.
1029 // The teardown path should be the same, see http://crbug.com/110228
1030 void ExpectSeekStop(TeardownState state) {
1031 base::Closure stop_cb = base::Bind(
1032 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1033
1034 if (state == kPausing) {
1035 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
1036 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure()));
1037 } else {
1038 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure());
1039 }
1040
1041 if (state == kFlushing) {
1042 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
1043 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure()));
1044 } else {
1045 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure());
1046 }
1047
1048 if (state == kSeeking) {
1049 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _))
1050 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunPipelineStatusCB()));
1051 } else {
1052 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _))
1053 .WillOnce(RunPipelineStatusCB());
1054 }
1055
1056 if (state == kPrerolling) {
1057 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _))
1058 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunPipelineStatusCB()));
1059 } else {
1060 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _))
1061 .WillOnce(RunPipelineStatusCB());
1062 }
1063
1064 if (state == kStarting) {
1065 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
1066 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure()));
1067 } else {
1068 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)).WillOnce(RunClosure());
1069 }
1070
1071 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
1072 ExpectStop();
1073 }
1074
1075 void ExpectSeekError(TeardownState state) {
1076 SetSeekErrorExpectations(state);
1077
1078 // Executed after the error is raised.
1079 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
1080 EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure());
1081 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure());
1082 }
1083
1084 void SetSeekErrorExpectations(TeardownState state) {
1085 if (state == kPausing) {
1086 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_))
1087 .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ),
1088 RunClosure()));
1089 return;
1090 }
1091
1092 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure());
1093
1094 if (state == kFlushing) {
1095 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_))
1096 .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ),
1097 RunClosure()));
1098 return;
1099 }
1100
1101 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure());
1102
1103 if (state == kSeeking) {
1104 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _))
1105 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ));
1106 return;
1107 }
1108
1109 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _))
1110 .WillOnce(RunPipelineStatusCB());
1111
1112 if (state == kPrerolling) {
1113 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _))
1114 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ));
1115 return;
1116 }
1117
1118 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _))
1119 .WillOnce(RunPipelineStatusCB());
1120
1121 if (state == kStarting) {
1122 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
1123 .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ),
1124 RunClosure()));
1125 return;
1126 }
1127
1128 NOTREACHED() << "Unexpected TeardownState: " << state;
1129 }
1130
1131 void ExpectStop() {
1132 // TODO(scherkus): Don't pause+flush, see http://crbug.com/110228
1133 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure());
1134 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure());
1135 EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure());
1136 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure());
1137
1138 EXPECT_CALL(callbacks_, OnStop());
1139 }
1140
1141 void ExpectPlaybackError() {
1142 // TODO(scherkus): Don't pause+flush, see http://crbug.com/110228
1143 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure());
1144 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure());
1145 EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure());
1146 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure());
1147
1148 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1149 }
1150
1151 void DoSeek() {
1152 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1153 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1154 message_loop_.RunAllPending();
1155 }
1156
1157 void DoStop() {
1158 pipeline_->Stop(base::Bind(
1159 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1160 message_loop_.RunAllPending();
1161 }
1162
1163 void DoPlaybackError() {
1164 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1165 message_loop_.RunAllPending();
1166 }
1167
1168 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1169 };
1170
1171 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1172 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1173 RunTest(k##state, k##stop_or_error); \
1174 }
1175
1176 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing);
1177 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1178 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1179 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1180 INSTANTIATE_TEARDOWN_TEST(Stop, Starting);
1181 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1182
1183 INSTANTIATE_TEARDOWN_TEST(Error, Pausing);
1184 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1185 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1186 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1187 INSTANTIATE_TEARDOWN_TEST(Error, Starting);
1188 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1189
960 } // namespace media 1190 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698