audio_input_device_manager_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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.
4
5#include <string>
6
7#include "base/bind.h"
8#include "base/memory/ref_counted.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/message_loop/message_loop.h"
11#include "base/synchronization/waitable_event.h"
12#include "content/browser/browser_thread_impl.h"
13#include "content/browser/renderer_host/media/audio_input_device_manager.h"
14#include "content/public/common/media_stream_request.h"
15#include "media/audio/audio_manager_base.h"
16#include "testing/gmock/include/gmock/gmock.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19using testing::_;
20using testing::InSequence;
21using testing::SaveArg;
22using testing::Return;
23
24namespace content {
25
26class MockAudioInputDeviceManagerListener
27    : public MediaStreamProviderListener {
28 public:
29  MockAudioInputDeviceManagerListener() {}
30  virtual ~MockAudioInputDeviceManagerListener() {}
31
32  MOCK_METHOD2(Opened, void(MediaStreamType, const int));
33  MOCK_METHOD2(Closed, void(MediaStreamType, const int));
34  MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType,
35                                       const StreamDeviceInfoArray&));
36  MOCK_METHOD3(Error, void(MediaStreamType, int, MediaStreamProviderError));
37
38  StreamDeviceInfoArray devices_;
39
40 private:
41  DISALLOW_COPY_AND_ASSIGN(MockAudioInputDeviceManagerListener);
42};
43
44// TODO(henrika): there are special restrictions for Android since
45// AudioInputDeviceManager::Open() must be called on the audio thread.
46// This test suite must be modified to run on Android.
47#if defined(OS_ANDROID)
48#define MAYBE_AudioInputDeviceManagerTest DISABLED_AudioInputDeviceManagerTest
49#else
50#define MAYBE_AudioInputDeviceManagerTest AudioInputDeviceManagerTest
51#endif
52
53class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
54 public:
55  MAYBE_AudioInputDeviceManagerTest() {}
56
57  // Returns true iff machine has an audio input device.
58  bool CanRunAudioInputDeviceTests() {
59    return audio_manager_->HasAudioInputDevices();
60  }
61
62 protected:
63  virtual void SetUp() OVERRIDE {
64    // The test must run on Browser::IO.
65    message_loop_.reset(new base::MessageLoopForIO);
66    io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
67                                           message_loop_.get()));
68    audio_manager_.reset(media::AudioManager::CreateForTesting());
69    // Wait for audio thread initialization to complete.  Otherwise the
70    // enumeration type may not have been set yet.
71    base::WaitableEvent event(false, false);
72    audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
73        &base::WaitableEvent::Signal, base::Unretained(&event)));
74    event.Wait();
75    manager_ = new AudioInputDeviceManager(audio_manager_.get());
76    audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
77    manager_->Register(audio_input_listener_.get(),
78                       message_loop_->message_loop_proxy().get());
79
80    // Gets the enumerated device list from the AudioInputDeviceManager.
81    manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
82    EXPECT_CALL(*audio_input_listener_,
83                DevicesEnumerated(MEDIA_DEVICE_AUDIO_CAPTURE, _))
84        .Times(1)
85        .WillOnce(SaveArg<1>(&devices_));
86
87    // Wait until we get the list.
88    message_loop_->RunUntilIdle();
89  }
90
91  virtual void TearDown() OVERRIDE {
92    manager_->Unregister();
93    io_thread_.reset();
94  }
95
96  scoped_ptr<base::MessageLoop> message_loop_;
97  scoped_ptr<BrowserThreadImpl> io_thread_;
98  scoped_refptr<AudioInputDeviceManager> manager_;
99  scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
100  scoped_ptr<media::AudioManager> audio_manager_;
101  StreamDeviceInfoArray devices_;
102
103 private:
104  DISALLOW_COPY_AND_ASSIGN(MAYBE_AudioInputDeviceManagerTest);
105};
106
107// Opens and closes the devices.
108TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenAndCloseDevice) {
109  if (!CanRunAudioInputDeviceTests())
110    return;
111
112  ASSERT_FALSE(devices_.empty());
113
114  InSequence s;
115
116  for (StreamDeviceInfoArray::const_iterator iter = devices_.begin();
117       iter != devices_.end(); ++iter) {
118    // Opens/closes the devices.
119    int session_id = manager_->Open(*iter);
120
121    // Expected mock call with expected return value.
122    EXPECT_CALL(*audio_input_listener_,
123                Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
124        .Times(1);
125    // Waits for the callback.
126    message_loop_->RunUntilIdle();
127
128    manager_->Close(session_id);
129    EXPECT_CALL(*audio_input_listener_,
130                Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
131        .Times(1);
132
133    // Waits for the callback.
134    message_loop_->RunUntilIdle();
135  }
136}
137
138// Opens multiple devices at one time and closes them later.
139TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenMultipleDevices) {
140  if (!CanRunAudioInputDeviceTests())
141    return;
142
143  ASSERT_FALSE(devices_.empty());
144
145  InSequence s;
146
147  int index = 0;
148  scoped_ptr<int[]> session_id(new int[devices_.size()]);
149
150  // Opens the devices in a loop.
151  for (StreamDeviceInfoArray::const_iterator iter = devices_.begin();
152       iter != devices_.end(); ++iter, ++index) {
153    // Opens the devices.
154    session_id[index] = manager_->Open(*iter);
155
156    // Expected mock call with expected returned value.
157    EXPECT_CALL(*audio_input_listener_,
158                Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index]))
159        .Times(1);
160
161    // Waits for the callback.
162    message_loop_->RunUntilIdle();
163  }
164
165  // Checks if the session_ids are unique.
166  for (size_t i = 0; i < devices_.size() - 1; ++i) {
167    for (size_t k = i + 1; k < devices_.size(); ++k) {
168      EXPECT_TRUE(session_id[i] != session_id[k]);
169    }
170  }
171
172  for (size_t i = 0; i < devices_.size(); ++i) {
173    // Closes the devices.
174    manager_->Close(session_id[i]);
175    EXPECT_CALL(*audio_input_listener_,
176                Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[i]))
177        .Times(1);
178
179    // Waits for the callback.
180    message_loop_->RunUntilIdle();
181  }
182}
183
184// Opens a non-existing device.
185TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenNotExistingDevice) {
186  if (!CanRunAudioInputDeviceTests())
187    return;
188  InSequence s;
189
190  MediaStreamType stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
191  std::string device_name("device_doesnt_exist");
192  std::string device_id("id_doesnt_exist");
193  int sample_rate(0);
194  int channel_config(0);
195  StreamDeviceInfo dummy_device(
196      stream_type, device_name, device_id, sample_rate, channel_config, 2048);
197
198  int session_id = manager_->Open(dummy_device);
199  EXPECT_CALL(*audio_input_listener_,
200              Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
201      .Times(1);
202
203  // Waits for the callback.
204  message_loop_->RunUntilIdle();
205}
206
207// Opens default device twice.
208TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenDeviceTwice) {
209  if (!CanRunAudioInputDeviceTests())
210    return;
211
212  ASSERT_FALSE(devices_.empty());
213
214  InSequence s;
215
216  // Opens and closes the default device twice.
217  int first_session_id = manager_->Open(devices_.front());
218  int second_session_id = manager_->Open(devices_.front());
219
220  // Expected mock calls with expected returned values.
221  EXPECT_NE(first_session_id, second_session_id);
222  EXPECT_CALL(*audio_input_listener_,
223              Opened(MEDIA_DEVICE_AUDIO_CAPTURE, first_session_id))
224      .Times(1);
225  EXPECT_CALL(*audio_input_listener_,
226              Opened(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id))
227      .Times(1);
228  // Waits for the callback.
229  message_loop_->RunUntilIdle();
230
231  manager_->Close(first_session_id);
232  manager_->Close(second_session_id);
233  EXPECT_CALL(*audio_input_listener_,
234              Closed(MEDIA_DEVICE_AUDIO_CAPTURE, first_session_id))
235      .Times(1);
236  EXPECT_CALL(*audio_input_listener_,
237              Closed(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id))
238      .Times(1);
239  // Waits for the callback.
240  message_loop_->RunUntilIdle();
241}
242
243// Accesses then closes the sessions after opening the devices.
244TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessAndCloseSession) {
245  if (!CanRunAudioInputDeviceTests())
246    return;
247
248  ASSERT_FALSE(devices_.empty());
249
250  InSequence s;
251
252  int index = 0;
253  scoped_ptr<int[]> session_id(new int[devices_.size()]);
254
255  // Loops through the devices and calls Open()/Close()/GetOpenedDeviceInfoById
256  // for each device.
257  for (StreamDeviceInfoArray::const_iterator iter = devices_.begin();
258       iter != devices_.end(); ++iter, ++index) {
259    // Note that no DeviceStopped() notification for Event Handler as we have
260    // stopped the device before calling close.
261    session_id[index] = manager_->Open(*iter);
262    EXPECT_CALL(*audio_input_listener_,
263                Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index]))
264        .Times(1);
265    message_loop_->RunUntilIdle();
266
267    const StreamDeviceInfo* info = manager_->GetOpenedDeviceInfoById(
268        session_id[index]);
269    DCHECK(info);
270    EXPECT_EQ(iter->device.id, info->device.id);
271    manager_->Close(session_id[index]);
272    EXPECT_CALL(*audio_input_listener_,
273                Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index]))
274        .Times(1);
275    message_loop_->RunUntilIdle();
276  }
277}
278
279// Access an invalid session.
280TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessInvalidSession) {
281  if (!CanRunAudioInputDeviceTests())
282    return;
283  InSequence s;
284
285  // Opens the first device.
286  StreamDeviceInfoArray::const_iterator iter = devices_.begin();
287  int session_id = manager_->Open(*iter);
288  EXPECT_CALL(*audio_input_listener_,
289              Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
290      .Times(1);
291  message_loop_->RunUntilIdle();
292
293  // Access a non-opened device.
294  // This should fail and return an empty StreamDeviceInfo.
295  int invalid_session_id = session_id + 1;
296  const StreamDeviceInfo* info =
297      manager_->GetOpenedDeviceInfoById(invalid_session_id);
298  DCHECK(!info);
299
300  manager_->Close(session_id);
301  EXPECT_CALL(*audio_input_listener_,
302              Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
303      .Times(1);
304  message_loop_->RunUntilIdle();
305}
306
307}  // namespace content
308