| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/environment.h" | 6 #include "base/environment.h" |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
| 10 #include "base/sync_socket.h" | 10 #include "base/sync_socket.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 static bool IsRunningHeadless() { | 36 static bool IsRunningHeadless() { |
| 37 scoped_ptr<base::Environment> env(base::Environment::Create()); | 37 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 38 if (env->HasVar("CHROME_HEADLESS")) | 38 if (env->HasVar("CHROME_HEADLESS")) |
| 39 return true; | 39 return true; |
| 40 return false; | 40 return false; |
| 41 } | 41 } |
| 42 | 42 |
| 43 class MockAudioRendererHost : public AudioRendererHost { | 43 class MockAudioRendererHost : public AudioRendererHost { |
| 44 public: | 44 public: |
| 45 MockAudioRendererHost(const content::ResourceContext* resource_context) | 45 explicit MockAudioRendererHost( |
| 46 const content::ResourceContext* resource_context) |
| 46 : AudioRendererHost(resource_context), | 47 : AudioRendererHost(resource_context), |
| 47 shared_memory_length_(0) { | 48 shared_memory_length_(0) { |
| 48 } | 49 } |
| 49 | 50 |
| 50 virtual ~MockAudioRendererHost() { | 51 virtual ~MockAudioRendererHost() { |
| 51 } | 52 } |
| 52 | 53 |
| 53 // A list of mock methods. | 54 // A list of mock methods. |
| 54 MOCK_METHOD2(OnRequestPacket, | 55 MOCK_METHOD2(OnRequestPacket, |
| 55 void(int stream_id, AudioBuffersState buffers_state)); | 56 void(int stream_id, AudioBuffersState buffers_state)); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 protected: | 176 protected: |
| 176 virtual void SetUp() { | 177 virtual void SetUp() { |
| 177 // Create a message loop so AudioRendererHost can use it. | 178 // Create a message loop so AudioRendererHost can use it. |
| 178 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); | 179 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); |
| 179 | 180 |
| 180 // Claim to be on both the UI and IO threads to pass all the DCHECKS. | 181 // Claim to be on both the UI and IO threads to pass all the DCHECKS. |
| 181 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, | 182 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, |
| 182 message_loop_.get())); | 183 message_loop_.get())); |
| 183 ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, | 184 ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, |
| 184 message_loop_.get())); | 185 message_loop_.get())); |
| 185 | 186 audio_manager_ = AudioManager::Create(); |
| 186 observer_.reset(new MockMediaObserver()); | 187 observer_.reset(new MockMediaObserver()); |
| 187 content::MockResourceContext* context = | 188 content::MockResourceContext* context = |
| 188 content::MockResourceContext::GetInstance(); | 189 content::MockResourceContext::GetInstance(); |
| 189 context->set_media_observer(observer_.get()); | 190 context->set_media_observer(observer_.get()); |
| 191 context->set_audio_manager(audio_manager_.get()); |
| 190 host_ = new MockAudioRendererHost(context); | 192 host_ = new MockAudioRendererHost(context); |
| 191 | 193 |
| 192 // Simulate IPC channel connected. | 194 // Simulate IPC channel connected. |
| 193 host_->OnChannelConnected(base::GetCurrentProcId()); | 195 host_->OnChannelConnected(base::GetCurrentProcId()); |
| 194 } | 196 } |
| 195 | 197 |
| 196 virtual void TearDown() { | 198 virtual void TearDown() { |
| 197 // Simulate closing the IPC channel. | 199 // Simulate closing the IPC channel. |
| 198 host_->OnChannelClosing(); | 200 host_->OnChannelClosing(); |
| 199 | 201 |
| 200 // Release the reference to the mock object. The object will be destructed | 202 // Release the reference to the mock object. The object will be destructed |
| 201 // on message_loop_. | 203 // on message_loop_. |
| 202 host_ = NULL; | 204 host_ = NULL; |
| 203 | 205 |
| 204 // We need to continue running message_loop_ to complete all destructions. | 206 // We need to continue running message_loop_ to complete all destructions. |
| 205 SyncWithAudioThread(); | 207 SyncWithAudioThread(); |
| 206 | 208 |
| 209 // Since the MockResourceContext object is a singleton that lives across |
| 210 // multiple tests, we must clear pointers to objects that are about to die. |
| 211 content::MockResourceContext* context = |
| 212 content::MockResourceContext::GetInstance(); |
| 213 context->set_audio_manager(NULL); |
| 214 context->set_media_observer(NULL); |
| 215 audio_manager_ = NULL; |
| 216 |
| 207 io_thread_.reset(); | 217 io_thread_.reset(); |
| 208 ui_thread_.reset(); | 218 ui_thread_.reset(); |
| 209 } | 219 } |
| 210 | 220 |
| 211 void Create() { | 221 void Create() { |
| 212 EXPECT_CALL(*observer_, | 222 EXPECT_CALL(*observer_, |
| 213 OnSetAudioStreamStatus(_, kStreamId, "created")); | 223 OnSetAudioStreamStatus(_, kStreamId, "created")); |
| 214 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); | 224 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)); |
| 215 | 225 |
| 216 InSequence s; | 226 InSequence s; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 // Expect the audio stream record is removed. | 341 // Expect the audio stream record is removed. |
| 332 EXPECT_EQ(0u, host_->audio_entries_.size()); | 342 EXPECT_EQ(0u, host_->audio_entries_.size()); |
| 333 } | 343 } |
| 334 | 344 |
| 335 // Called on the audio thread. | 345 // Called on the audio thread. |
| 336 static void PostQuitMessageLoop(MessageLoop* message_loop) { | 346 static void PostQuitMessageLoop(MessageLoop* message_loop) { |
| 337 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | 347 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 338 } | 348 } |
| 339 | 349 |
| 340 // Called on the main thread. | 350 // Called on the main thread. |
| 341 static void PostQuitOnAudioThread(MessageLoop* message_loop) { | 351 static void PostQuitOnAudioThread(AudioManager* audio_manager, |
| 342 AudioManager::GetAudioManager()->GetMessageLoop()->PostTask( | 352 MessageLoop* message_loop) { |
| 343 FROM_HERE, base::Bind(&PostQuitMessageLoop, message_loop)); | 353 audio_manager->GetMessageLoop()->PostTask(FROM_HERE, |
| 354 base::Bind(&PostQuitMessageLoop, message_loop)); |
| 344 } | 355 } |
| 345 | 356 |
| 346 // SyncWithAudioThread() waits until all pending tasks on the audio thread | 357 // SyncWithAudioThread() waits until all pending tasks on the audio thread |
| 347 // are executed while also processing pending task in message_loop_ on the | 358 // are executed while also processing pending task in message_loop_ on the |
| 348 // current thread. It is used to synchronize with the audio thread when we are | 359 // current thread. It is used to synchronize with the audio thread when we are |
| 349 // closing an audio stream. | 360 // closing an audio stream. |
| 350 void SyncWithAudioThread() { | 361 void SyncWithAudioThread() { |
| 362 // Don't use scoped_refptr to addref the AudioManager when posting |
| 363 // to the thread that itself owns. |
| 351 message_loop_->PostTask( | 364 message_loop_->PostTask( |
| 352 FROM_HERE, base::Bind(&PostQuitOnAudioThread, message_loop_.get())); | 365 FROM_HERE, base::Bind(&PostQuitOnAudioThread, |
| 366 base::Unretained(audio_manager_.get()), |
| 367 message_loop_.get())); |
| 353 message_loop_->Run(); | 368 message_loop_->Run(); |
| 354 } | 369 } |
| 355 | 370 |
| 356 MessageLoop* message_loop() { return message_loop_.get(); } | 371 MessageLoop* message_loop() { return message_loop_.get(); } |
| 357 MockAudioRendererHost* host() { return host_; } | 372 MockAudioRendererHost* host() { return host_; } |
| 358 void EnableRealDevice() { mock_stream_ = false; } | 373 void EnableRealDevice() { mock_stream_ = false; } |
| 359 | 374 |
| 360 private: | 375 private: |
| 361 bool mock_stream_; | 376 bool mock_stream_; |
| 362 scoped_ptr<MockMediaObserver> observer_; | 377 scoped_ptr<MockMediaObserver> observer_; |
| 363 scoped_refptr<MockAudioRendererHost> host_; | 378 scoped_refptr<MockAudioRendererHost> host_; |
| 364 scoped_ptr<MessageLoop> message_loop_; | 379 scoped_ptr<MessageLoop> message_loop_; |
| 365 scoped_ptr<BrowserThreadImpl> io_thread_; | 380 scoped_ptr<BrowserThreadImpl> io_thread_; |
| 366 scoped_ptr<BrowserThreadImpl> ui_thread_; | 381 scoped_ptr<BrowserThreadImpl> ui_thread_; |
| 382 scoped_refptr<AudioManager> audio_manager_; |
| 367 | 383 |
| 368 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); | 384 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); |
| 369 }; | 385 }; |
| 370 | 386 |
| 371 TEST_F(AudioRendererHostTest, CreateAndClose) { | 387 TEST_F(AudioRendererHostTest, CreateAndClose) { |
| 372 if (!IsRunningHeadless()) | 388 if (!IsRunningHeadless()) |
| 373 EnableRealDevice(); | 389 EnableRealDevice(); |
| 374 | 390 |
| 375 Create(); | 391 Create(); |
| 376 Close(); | 392 Close(); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 | 513 |
| 498 // Simulate the case where a stream is not properly closed. | 514 // Simulate the case where a stream is not properly closed. |
| 499 TEST_F(AudioRendererHostTest, CreateLowLatencyAndShutdown) { | 515 TEST_F(AudioRendererHostTest, CreateLowLatencyAndShutdown) { |
| 500 if (!IsRunningHeadless()) | 516 if (!IsRunningHeadless()) |
| 501 EnableRealDevice(); | 517 EnableRealDevice(); |
| 502 | 518 |
| 503 CreateLowLatency(); | 519 CreateLowLatency(); |
| 504 } | 520 } |
| 505 | 521 |
| 506 // TODO(hclam): Add tests for data conversation in low latency mode. | 522 // TODO(hclam): Add tests for data conversation in low latency mode. |
| OLD | NEW |