ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / content / browser / renderer_host / media / audio_renderer_host_unittest.cc
blob8370782bed36650115f23bc0afa2c2010c28e963
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.
5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/sync_socket.h"
10 #include "content/browser/media/capture/audio_mirroring_manager.h"
11 #include "content/browser/media/media_internals.h"
12 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
13 #include "content/browser/renderer_host/media/audio_renderer_host.h"
14 #include "content/browser/renderer_host/media/media_stream_manager.h"
15 #include "content/common/media/audio_messages.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "ipc/ipc_message_utils.h"
19 #include "media/audio/audio_manager.h"
20 #include "media/base/bind_to_current_loop.h"
21 #include "media/base/media_switches.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using ::testing::_;
26 using ::testing::Assign;
27 using ::testing::DoAll;
28 using ::testing::NotNull;
30 namespace {
31 const int kRenderProcessId = 1;
32 const int kRenderViewId = 4;
33 const int kRenderFrameId = 5;
34 const int kStreamId = 50;
35 } // namespace
37 namespace content {
39 class MockAudioMirroringManager : public AudioMirroringManager {
40 public:
41 MockAudioMirroringManager() {}
42 virtual ~MockAudioMirroringManager() {}
44 MOCK_METHOD3(AddDiverter,
45 void(int render_process_id,
46 int render_frame_id,
47 Diverter* diverter));
48 MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter));
50 private:
51 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
54 class MockAudioRendererHost : public AudioRendererHost {
55 public:
56 MockAudioRendererHost(media::AudioManager* audio_manager,
57 AudioMirroringManager* mirroring_manager,
58 MediaInternals* media_internals,
59 MediaStreamManager* media_stream_manager)
60 : AudioRendererHost(kRenderProcessId,
61 audio_manager,
62 mirroring_manager,
63 media_internals,
64 media_stream_manager),
65 shared_memory_length_(0) {}
67 // A list of mock methods.
68 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
69 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
70 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
71 MOCK_METHOD1(OnStreamError, void(int stream_id));
73 private:
74 virtual ~MockAudioRendererHost() {
75 // Make sure all audio streams have been deleted.
76 EXPECT_TRUE(audio_entries_.empty());
79 // This method is used to dispatch IPC messages to the renderer. We intercept
80 // these messages here and dispatch to our mock methods to verify the
81 // conversation between this object and the renderer.
82 virtual bool Send(IPC::Message* message) {
83 CHECK(message);
85 // In this method we dispatch the messages to the according handlers as if
86 // we are the renderer.
87 bool handled = true;
88 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
89 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
90 OnNotifyStreamCreated)
91 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
92 OnNotifyStreamStateChanged)
93 IPC_MESSAGE_UNHANDLED(handled = false)
94 IPC_END_MESSAGE_MAP()
95 EXPECT_TRUE(handled);
97 delete message;
98 return true;
101 void OnNotifyStreamCreated(
102 int stream_id, base::SharedMemoryHandle handle,
103 base::SyncSocket::TransitDescriptor socket_descriptor, uint32 length) {
104 // Maps the shared memory.
105 shared_memory_.reset(new base::SharedMemory(handle, false));
106 CHECK(shared_memory_->Map(length));
107 CHECK(shared_memory_->memory());
108 shared_memory_length_ = length;
110 // Create the SyncSocket using the handle.
111 base::SyncSocket::Handle sync_socket_handle =
112 base::SyncSocket::UnwrapHandle(socket_descriptor);
113 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
115 // And then delegate the call to the mock method.
116 OnStreamCreated(stream_id, length);
119 void OnNotifyStreamStateChanged(int stream_id,
120 media::AudioOutputIPCDelegate::State state) {
121 switch (state) {
122 case media::AudioOutputIPCDelegate::kPlaying:
123 OnStreamPlaying(stream_id);
124 break;
125 case media::AudioOutputIPCDelegate::kPaused:
126 OnStreamPaused(stream_id);
127 break;
128 case media::AudioOutputIPCDelegate::kError:
129 OnStreamError(stream_id);
130 break;
131 default:
132 FAIL() << "Unknown stream state";
133 break;
137 scoped_ptr<base::SharedMemory> shared_memory_;
138 scoped_ptr<base::SyncSocket> sync_socket_;
139 uint32 shared_memory_length_;
141 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
144 class AudioRendererHostTest : public testing::Test {
145 public:
146 AudioRendererHostTest() {
147 audio_manager_.reset(media::AudioManager::CreateForTesting());
148 base::CommandLine::ForCurrentProcess()->AppendSwitch(
149 switches::kUseFakeDeviceForMediaStream);
150 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
151 host_ = new MockAudioRendererHost(audio_manager_.get(),
152 &mirroring_manager_,
153 MediaInternals::GetInstance(),
154 media_stream_manager_.get());
156 // Simulate IPC channel connected.
157 host_->set_peer_process_for_testing(base::Process::Current());
160 ~AudioRendererHostTest() override {
161 // Simulate closing the IPC channel and give the audio thread time to close
162 // the underlying streams.
163 host_->OnChannelClosing();
164 SyncWithAudioThread();
166 // Release the reference to the mock object. The object will be destructed
167 // on message_loop_.
168 host_ = NULL;
171 protected:
172 void Create(bool unified_stream) {
173 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
175 EXPECT_CALL(mirroring_manager_,
176 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
177 .RetiresOnSaturation();
179 // Send a create stream message to the audio output stream and wait until
180 // we receive the created message.
181 int session_id;
182 media::AudioParameters params;
183 if (unified_stream) {
184 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
185 // pass the permission check.
186 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
187 params = media::AudioParameters(
188 media::AudioParameters::AUDIO_FAKE,
189 media::CHANNEL_LAYOUT_STEREO,
190 media::AudioParameters::kAudioCDSampleRate, 16,
191 media::AudioParameters::kAudioCDSampleRate / 10,
192 media::AudioParameters::NO_EFFECTS);
193 } else {
194 session_id = 0;
195 params = media::AudioParameters(
196 media::AudioParameters::AUDIO_FAKE,
197 media::CHANNEL_LAYOUT_STEREO,
198 media::AudioParameters::kAudioCDSampleRate, 16,
199 media::AudioParameters::kAudioCDSampleRate / 10);
201 host_->OnCreateStream(kStreamId, kRenderViewId, kRenderFrameId, session_id,
202 params);
204 // At some point in the future, a corresponding RemoveDiverter() call must
205 // be made.
206 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
207 .RetiresOnSaturation();
208 SyncWithAudioThread();
211 void Close() {
212 // Send a message to AudioRendererHost to tell it we want to close the
213 // stream.
214 host_->OnCloseStream(kStreamId);
215 SyncWithAudioThread();
218 void Play() {
219 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
220 host_->OnPlayStream(kStreamId);
221 SyncWithAudioThread();
224 void Pause() {
225 EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId));
226 host_->OnPauseStream(kStreamId);
227 SyncWithAudioThread();
230 void SetVolume(double volume) {
231 host_->OnSetVolume(kStreamId, volume);
232 SyncWithAudioThread();
235 void SimulateError() {
236 EXPECT_EQ(1u, host_->audio_entries_.size())
237 << "Calls Create() before calling this method";
239 // Expect an error signal sent through IPC.
240 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId));
242 // Simulate an error sent from the audio device.
243 host_->ReportErrorAndClose(kStreamId);
244 SyncWithAudioThread();
246 // Expect the audio stream record is removed.
247 EXPECT_EQ(0u, host_->audio_entries_.size());
250 // SyncWithAudioThread() waits until all pending tasks on the audio thread
251 // are executed while also processing pending task in message_loop_ on the
252 // current thread. It is used to synchronize with the audio thread when we are
253 // closing an audio stream.
254 void SyncWithAudioThread() {
255 base::RunLoop().RunUntilIdle();
257 base::RunLoop run_loop;
258 audio_manager_->GetTaskRunner()->PostTask(
259 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
260 run_loop.Run();
263 private:
264 // MediaStreamManager uses a DestructionObserver, so it must outlive the
265 // TestBrowserThreadBundle.
266 scoped_ptr<MediaStreamManager> media_stream_manager_;
267 TestBrowserThreadBundle thread_bundle_;
268 scoped_ptr<media::AudioManager> audio_manager_;
269 MockAudioMirroringManager mirroring_manager_;
270 scoped_refptr<MockAudioRendererHost> host_;
272 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
275 TEST_F(AudioRendererHostTest, CreateAndClose) {
276 Create(false);
277 Close();
280 // Simulate the case where a stream is not properly closed.
281 TEST_F(AudioRendererHostTest, CreateAndShutdown) {
282 Create(false);
285 TEST_F(AudioRendererHostTest, CreatePlayAndClose) {
286 Create(false);
287 Play();
288 Close();
291 TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
292 Create(false);
293 Play();
294 Pause();
295 Close();
298 TEST_F(AudioRendererHostTest, SetVolume) {
299 Create(false);
300 SetVolume(0.5);
301 Play();
302 Pause();
303 Close();
306 // Simulate the case where a stream is not properly closed.
307 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
308 Create(false);
309 Play();
312 // Simulate the case where a stream is not properly closed.
313 TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) {
314 Create(false);
315 Play();
316 Pause();
319 TEST_F(AudioRendererHostTest, SimulateError) {
320 Create(false);
321 Play();
322 SimulateError();
325 // Simulate the case when an error is generated on the browser process,
326 // the audio device is closed but the render process try to close the
327 // audio stream again.
328 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
329 Create(false);
330 Play();
331 SimulateError();
332 Close();
335 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
336 Create(true);
337 Close();
340 // TODO(hclam): Add tests for data conversation in low latency mode.
342 } // namespace content