| OLD | NEW |
| 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 <list> | 5 #include <list> |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 } | 90 } |
| 91 | 91 |
| 92 private: | 92 private: |
| 93 base::WaitableEvent data_pulled_; | 93 base::WaitableEvent data_pulled_; |
| 94 | 94 |
| 95 DISALLOW_COPY_AND_ASSIGN(TestAudioSource); | 95 DISALLOW_COPY_AND_ASSIGN(TestAudioSource); |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 } // namespace | 98 } // namespace |
| 99 | 99 |
| 100 class VirtualAudioInputStreamTest : public testing::Test { | 100 class VirtualAudioInputStreamTest : public testing::TestWithParam<bool> { |
| 101 public: | 101 public: |
| 102 VirtualAudioInputStreamTest() | 102 VirtualAudioInputStreamTest() |
| 103 : audio_thread_(new base::Thread("AudioThread")), | 103 : audio_thread_(new base::Thread("AudioThread")), |
| 104 worker_thread_(new base::Thread("AudioWorkerThread")), |
| 104 stream_(NULL), | 105 stream_(NULL), |
| 105 closed_stream_(false, false) { | 106 closed_stream_(false, false) { |
| 106 audio_thread_->Start(); | 107 audio_thread_->Start(); |
| 107 audio_message_loop_ = audio_thread_->message_loop_proxy(); | 108 audio_message_loop_ = audio_thread_->message_loop_proxy(); |
| 108 } | 109 } |
| 109 | 110 |
| 110 virtual ~VirtualAudioInputStreamTest() { | 111 virtual ~VirtualAudioInputStreamTest() { |
| 111 SyncWithAudioThread(); | 112 SyncWithAudioThread(); |
| 112 | 113 |
| 113 DCHECK(output_streams_.empty()); | 114 DCHECK(output_streams_.empty()); |
| 114 DCHECK(stopped_output_streams_.empty()); | 115 DCHECK(stopped_output_streams_.empty()); |
| 115 } | 116 } |
| 116 | 117 |
| 117 void Create() { | 118 void Create() { |
| 119 const bool worker_is_separate_thread = GetParam(); |
| 118 stream_ = new VirtualAudioInputStream( | 120 stream_ = new VirtualAudioInputStream( |
| 119 kParams, audio_message_loop_, | 121 kParams, GetWorkerLoop(worker_is_separate_thread), |
| 120 base::Bind(&base::DeletePointer<VirtualAudioInputStream>)); | 122 base::Bind(&base::DeletePointer<VirtualAudioInputStream>)); |
| 121 stream_->Open(); | 123 stream_->Open(); |
| 122 } | 124 } |
| 123 | 125 |
| 124 void Start() { | 126 void Start() { |
| 125 EXPECT_CALL(input_callback_, OnClose(_)); | 127 EXPECT_CALL(input_callback_, OnClose(_)); |
| 126 EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _)) | 128 EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _)) |
| 127 .Times(AtLeast(1)); | 129 .Times(AtLeast(1)); |
| 128 | 130 |
| 129 ASSERT_TRUE(!!stream_); | 131 ASSERT_TRUE(!!stream_); |
| 130 stream_->Start(&input_callback_); | 132 stream_->Start(&input_callback_); |
| 131 } | 133 } |
| 132 | 134 |
| 133 void CreateAndStartOneOutputStream() { | 135 void CreateAndStartOneOutputStream() { |
| 134 ASSERT_TRUE(!!stream_); | 136 ASSERT_TRUE(!!stream_); |
| 135 AudioOutputStream* const output_stream = new VirtualAudioOutputStream( | 137 AudioOutputStream* const output_stream = new VirtualAudioOutputStream( |
| 136 kParams, | 138 kParams, |
| 137 audio_message_loop_.get(), | |
| 138 stream_, | 139 stream_, |
| 139 base::Bind(&base::DeletePointer<VirtualAudioOutputStream>)); | 140 base::Bind(&base::DeletePointer<VirtualAudioOutputStream>)); |
| 140 output_streams_.push_back(output_stream); | 141 output_streams_.push_back(output_stream); |
| 141 | 142 |
| 142 output_stream->Open(); | 143 output_stream->Open(); |
| 143 output_stream->Start(&source_); | 144 output_stream->Start(&source_); |
| 144 } | 145 } |
| 145 | 146 |
| 146 void Stop() { | 147 void Stop() { |
| 147 ASSERT_TRUE(!!stream_); | 148 ASSERT_TRUE(!!stream_); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 (*it)->Start(&source_); | 206 (*it)->Start(&source_); |
| 206 output_streams_.push_back(*it); | 207 output_streams_.push_back(*it); |
| 207 } | 208 } |
| 208 stopped_output_streams_.clear(); | 209 stopped_output_streams_.clear(); |
| 209 } | 210 } |
| 210 | 211 |
| 211 const scoped_refptr<base::MessageLoopProxy>& audio_message_loop() const { | 212 const scoped_refptr<base::MessageLoopProxy>& audio_message_loop() const { |
| 212 return audio_message_loop_; | 213 return audio_message_loop_; |
| 213 } | 214 } |
| 214 | 215 |
| 216 const scoped_refptr<base::MessageLoopProxy>& GetWorkerLoop( |
| 217 bool worker_is_separate_thread) { |
| 218 if (worker_is_separate_thread) { |
| 219 if (!worker_thread_->IsRunning()) { |
| 220 worker_thread_->Start(); |
| 221 worker_message_loop_ = worker_thread_->message_loop_proxy(); |
| 222 } |
| 223 return worker_message_loop_; |
| 224 } else { |
| 225 return audio_message_loop_; |
| 226 } |
| 227 } |
| 228 |
| 215 private: | 229 private: |
| 216 void SyncWithAudioThread() { | 230 void SyncWithAudioThread() { |
| 217 base::WaitableEvent done(false, false); | 231 base::WaitableEvent done(false, false); |
| 218 audio_message_loop_->PostTask( | 232 audio_message_loop_->PostTask( |
| 219 FROM_HERE, | 233 FROM_HERE, |
| 220 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); | 234 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); |
| 221 done.Wait(); | 235 done.Wait(); |
| 222 } | 236 } |
| 223 | 237 |
| 224 scoped_ptr<base::Thread> audio_thread_; | 238 scoped_ptr<base::Thread> audio_thread_; |
| 225 scoped_refptr<base::MessageLoopProxy> audio_message_loop_; | 239 scoped_refptr<base::MessageLoopProxy> audio_message_loop_; |
| 240 scoped_ptr<base::Thread> worker_thread_; |
| 241 scoped_refptr<base::MessageLoopProxy> worker_message_loop_; |
| 226 | 242 |
| 227 VirtualAudioInputStream* stream_; | 243 VirtualAudioInputStream* stream_; |
| 228 MockInputCallback input_callback_; | 244 MockInputCallback input_callback_; |
| 229 base::WaitableEvent closed_stream_; | 245 base::WaitableEvent closed_stream_; |
| 230 | 246 |
| 231 std::list<AudioOutputStream*> output_streams_; | 247 std::list<AudioOutputStream*> output_streams_; |
| 232 std::list<AudioOutputStream*> stopped_output_streams_; | 248 std::list<AudioOutputStream*> stopped_output_streams_; |
| 233 TestAudioSource source_; | 249 TestAudioSource source_; |
| 234 | 250 |
| 235 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); | 251 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); |
| 236 }; | 252 }; |
| 237 | 253 |
| 238 #define RUN_ON_AUDIO_THREAD(method) \ | 254 #define RUN_ON_AUDIO_THREAD(method) \ |
| 239 audio_message_loop()->PostTask( \ | 255 audio_message_loop()->PostTask( \ |
| 240 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \ | 256 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \ |
| 241 base::Unretained(this))) | 257 base::Unretained(this))) |
| 242 | 258 |
| 243 TEST_F(VirtualAudioInputStreamTest, CreateAndClose) { | 259 TEST_P(VirtualAudioInputStreamTest, CreateAndClose) { |
| 244 RUN_ON_AUDIO_THREAD(Create); | 260 RUN_ON_AUDIO_THREAD(Create); |
| 245 RUN_ON_AUDIO_THREAD(Close); | 261 RUN_ON_AUDIO_THREAD(Close); |
| 246 WaitUntilClosed(); | 262 WaitUntilClosed(); |
| 247 } | 263 } |
| 248 | 264 |
| 249 TEST_F(VirtualAudioInputStreamTest, NoOutputs) { | 265 TEST_P(VirtualAudioInputStreamTest, NoOutputs) { |
| 250 RUN_ON_AUDIO_THREAD(Create); | 266 RUN_ON_AUDIO_THREAD(Create); |
| 251 RUN_ON_AUDIO_THREAD(Start); | 267 RUN_ON_AUDIO_THREAD(Start); |
| 252 WaitForDataToFlow(); | 268 WaitForDataToFlow(); |
| 253 RUN_ON_AUDIO_THREAD(Stop); | 269 RUN_ON_AUDIO_THREAD(Stop); |
| 254 RUN_ON_AUDIO_THREAD(Close); | 270 RUN_ON_AUDIO_THREAD(Close); |
| 255 WaitUntilClosed(); | 271 WaitUntilClosed(); |
| 256 } | 272 } |
| 257 | 273 |
| 258 TEST_F(VirtualAudioInputStreamTest, SingleOutput) { | 274 TEST_P(VirtualAudioInputStreamTest, SingleOutput) { |
| 259 RUN_ON_AUDIO_THREAD(Create); | 275 RUN_ON_AUDIO_THREAD(Create); |
| 260 RUN_ON_AUDIO_THREAD(Start); | 276 RUN_ON_AUDIO_THREAD(Start); |
| 261 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); | 277 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); |
| 262 WaitForDataToFlow(); | 278 WaitForDataToFlow(); |
| 263 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 279 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 264 RUN_ON_AUDIO_THREAD(Stop); | 280 RUN_ON_AUDIO_THREAD(Stop); |
| 265 RUN_ON_AUDIO_THREAD(Close); | 281 RUN_ON_AUDIO_THREAD(Close); |
| 266 WaitUntilClosed(); | 282 WaitUntilClosed(); |
| 267 } | 283 } |
| 268 | 284 |
| 269 TEST_F(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) { | 285 TEST_P(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) { |
| 270 RUN_ON_AUDIO_THREAD(Create); | 286 RUN_ON_AUDIO_THREAD(Create); |
| 271 RUN_ON_AUDIO_THREAD(Start); | 287 RUN_ON_AUDIO_THREAD(Start); |
| 272 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); | 288 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); |
| 273 WaitForDataToFlow(); | 289 WaitForDataToFlow(); |
| 274 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); | 290 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); |
| 275 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); | 291 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); |
| 276 WaitForDataToFlow(); | 292 WaitForDataToFlow(); |
| 277 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 293 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 278 RUN_ON_AUDIO_THREAD(Stop); | 294 RUN_ON_AUDIO_THREAD(Stop); |
| 279 RUN_ON_AUDIO_THREAD(Close); | 295 RUN_ON_AUDIO_THREAD(Close); |
| 280 WaitUntilClosed(); | 296 WaitUntilClosed(); |
| 281 } | 297 } |
| 282 | 298 |
| 283 TEST_F(VirtualAudioInputStreamTest, MultipleOutputs) { | 299 TEST_P(VirtualAudioInputStreamTest, MultipleOutputs) { |
| 284 RUN_ON_AUDIO_THREAD(Create); | 300 RUN_ON_AUDIO_THREAD(Create); |
| 285 RUN_ON_AUDIO_THREAD(Start); | 301 RUN_ON_AUDIO_THREAD(Start); |
| 286 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); | 302 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); |
| 287 WaitForDataToFlow(); | 303 WaitForDataToFlow(); |
| 288 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); | 304 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); |
| 289 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); | 305 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); |
| 290 WaitForDataToFlow(); | 306 WaitForDataToFlow(); |
| 291 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); | 307 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); |
| 292 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); | 308 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); |
| 293 WaitForDataToFlow(); | 309 WaitForDataToFlow(); |
| 294 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); | 310 RUN_ON_AUDIO_THREAD(StopFirstOutputStream); |
| 295 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); | 311 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); |
| 296 WaitForDataToFlow(); | 312 WaitForDataToFlow(); |
| 297 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 313 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 298 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 314 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 299 RUN_ON_AUDIO_THREAD(Stop); | 315 RUN_ON_AUDIO_THREAD(Stop); |
| 300 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 316 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 301 RUN_ON_AUDIO_THREAD(Close); | 317 RUN_ON_AUDIO_THREAD(Close); |
| 302 WaitUntilClosed(); | 318 WaitUntilClosed(); |
| 303 } | 319 } |
| 304 | 320 |
| 305 // A combination of all of the above tests with many output streams. | 321 // A combination of all of the above tests with many output streams. |
| 306 TEST_F(VirtualAudioInputStreamTest, ComprehensiveTest) { | 322 TEST_P(VirtualAudioInputStreamTest, ComprehensiveTest) { |
| 307 static const int kNumOutputs = 8; | 323 static const int kNumOutputs = 8; |
| 308 static const int kHalfNumOutputs = kNumOutputs / 2; | 324 static const int kHalfNumOutputs = kNumOutputs / 2; |
| 309 static const int kPauseIterations = 5; | 325 static const int kPauseIterations = 5; |
| 310 | 326 |
| 311 RUN_ON_AUDIO_THREAD(Create); | 327 RUN_ON_AUDIO_THREAD(Create); |
| 312 for (int i = 0; i < kHalfNumOutputs; ++i) { | 328 for (int i = 0; i < kHalfNumOutputs; ++i) { |
| 313 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); | 329 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); |
| 314 } | 330 } |
| 315 RUN_ON_AUDIO_THREAD(Start); | 331 RUN_ON_AUDIO_THREAD(Start); |
| 316 WaitForDataToFlow(); | 332 WaitForDataToFlow(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 328 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 344 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 329 } | 345 } |
| 330 RUN_ON_AUDIO_THREAD(Stop); | 346 RUN_ON_AUDIO_THREAD(Stop); |
| 331 for (int i = 0; i < kHalfNumOutputs; ++i) { | 347 for (int i = 0; i < kHalfNumOutputs; ++i) { |
| 332 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); | 348 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); |
| 333 } | 349 } |
| 334 RUN_ON_AUDIO_THREAD(Close); | 350 RUN_ON_AUDIO_THREAD(Close); |
| 335 WaitUntilClosed(); | 351 WaitUntilClosed(); |
| 336 } | 352 } |
| 337 | 353 |
| 354 INSTANTIATE_TEST_CASE_P(SingleVersusMultithreaded, |
| 355 VirtualAudioInputStreamTest, |
| 356 ::testing::Values(false, true)); |
| 357 |
| 338 } // namespace media | 358 } // namespace media |
| OLD | NEW |