[MemSheriff] More sendto parameter issues.
[chromium-blink-merge.git] / media / audio / audio_manager_unittest.cc
blob930e776c5f570fa64563623db9b2d6b1a9bfb93e
1 // Copyright 2013 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/environment.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "media/audio/audio_manager.h"
11 #include "media/audio/audio_manager_base.h"
12 #include "media/audio/fake_audio_log_factory.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 #if defined(USE_ALSA)
16 #include "media/audio/alsa/audio_manager_alsa.h"
17 #endif // defined(USE_ALSA)
19 #if defined(OS_WIN)
20 #include "base/win/scoped_com_initializer.h"
21 #include "media/audio/win/audio_manager_win.h"
22 #include "media/audio/win/wavein_input_win.h"
23 #endif
25 #if defined(USE_PULSEAUDIO)
26 #include "media/audio/pulse/audio_manager_pulse.h"
27 #endif // defined(USE_PULSEAUDIO)
29 namespace media {
31 // Test fixture which allows us to override the default enumeration API on
32 // Windows.
33 class AudioManagerTest : public ::testing::Test {
34 protected:
35 AudioManagerTest()
36 : audio_manager_(AudioManager::CreateForTesting())
37 #if defined(OS_WIN)
38 , com_init_(base::win::ScopedCOMInitializer::kMTA)
39 #endif
41 // Wait for audio thread initialization to complete. Otherwise the
42 // enumeration type may not have been set yet.
43 base::WaitableEvent event(false, false);
44 audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
45 &base::WaitableEvent::Signal, base::Unretained(&event)));
46 event.Wait();
49 AudioManager* audio_manager() { return audio_manager_.get(); };
51 #if defined(OS_WIN)
52 bool SetMMDeviceEnumeration() {
53 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
54 // Windows Wave is used as default if Windows XP was detected =>
55 // return false since MMDevice is not supported on XP.
56 if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration)
57 return false;
59 amw->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration);
60 return true;
63 void SetWaveEnumeration() {
64 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
65 amw->SetEnumerationType(AudioManagerWin::kWaveEnumeration);
68 std::string GetDeviceIdFromPCMWaveInAudioInputStream(
69 const std::string& device_id) {
70 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get());
71 AudioParameters parameters(
72 AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
73 AudioParameters::kAudioCDSampleRate, 16,
74 1024);
75 scoped_ptr<PCMWaveInAudioInputStream> stream(
76 static_cast<PCMWaveInAudioInputStream*>(
77 amw->CreatePCMWaveInAudioInputStream(parameters, device_id)));
78 return stream.get() ? stream->device_id_ : std::string();
80 #endif
82 // Helper method which verifies that the device list starts with a valid
83 // default record followed by non-default device names.
84 static void CheckDeviceNames(const AudioDeviceNames& device_names) {
85 DVLOG(2) << "Got " << device_names.size() << " audio devices.";
86 if (!device_names.empty()) {
87 AudioDeviceNames::const_iterator it = device_names.begin();
89 // The first device in the list should always be the default device.
90 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName),
91 it->device_name);
92 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id);
93 ++it;
95 // Other devices should have non-empty name and id and should not contain
96 // default name or id.
97 while (it != device_names.end()) {
98 EXPECT_FALSE(it->device_name.empty());
99 EXPECT_FALSE(it->unique_id.empty());
100 DVLOG(2) << "Device ID(" << it->unique_id
101 << "), label: " << it->device_name;
102 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName),
103 it->device_name);
104 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId),
105 it->unique_id);
106 ++it;
108 } else {
109 // Log a warning so we can see the status on the build bots. No need to
110 // break the test though since this does successfully test the code and
111 // some failure cases.
112 LOG(WARNING) << "No input devices detected";
116 bool CanRunInputTest() {
117 return audio_manager_->HasAudioInputDevices();
120 bool CanRunOutputTest() {
121 return audio_manager_->HasAudioOutputDevices();
124 #if defined(USE_ALSA) || defined(USE_PULSEAUDIO)
125 template <class T>
126 void CreateAudioManagerForTesting() {
127 // Only one AudioManager may exist at a time, so destroy the one we're
128 // currently holding before creating a new one.
129 audio_manager_.reset();
130 audio_manager_.reset(T::Create(&fake_audio_log_factory_));
132 #endif
134 // Synchronously runs the provided callback/closure on the audio thread.
135 void RunOnAudioThread(const base::Closure& closure) {
136 if (!audio_manager()->GetTaskRunner()->BelongsToCurrentThread()) {
137 base::WaitableEvent event(false, false);
138 audio_manager_->GetTaskRunner()->PostTask(
139 FROM_HERE,
140 base::Bind(&AudioManagerTest::RunOnAudioThreadImpl,
141 base::Unretained(this),
142 closure,
143 &event));
144 event.Wait();
145 } else {
146 closure.Run();
150 void RunOnAudioThreadImpl(const base::Closure& closure,
151 base::WaitableEvent* event) {
152 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread());
153 closure.Run();
154 event->Signal();
157 FakeAudioLogFactory fake_audio_log_factory_;
158 scoped_ptr<AudioManager> audio_manager_;
160 #if defined(OS_WIN)
161 // The MMDevice API requires COM to be initialized on the current thread.
162 base::win::ScopedCOMInitializer com_init_;
163 #endif
166 // Test that devices can be enumerated.
167 TEST_F(AudioManagerTest, EnumerateInputDevices) {
168 if (!CanRunInputTest())
169 return;
171 AudioDeviceNames device_names;
172 RunOnAudioThread(
173 base::Bind(&AudioManager::GetAudioInputDeviceNames,
174 base::Unretained(audio_manager()),
175 &device_names));
176 CheckDeviceNames(device_names);
179 // Test that devices can be enumerated.
180 TEST_F(AudioManagerTest, EnumerateOutputDevices) {
181 if (!CanRunOutputTest())
182 return;
184 AudioDeviceNames device_names;
185 RunOnAudioThread(
186 base::Bind(&AudioManager::GetAudioOutputDeviceNames,
187 base::Unretained(audio_manager()),
188 &device_names));
189 CheckDeviceNames(device_names);
192 // Run additional tests for Windows since enumeration can be done using
193 // two different APIs. MMDevice is default for Vista and higher and Wave
194 // is default for XP and lower.
195 #if defined(OS_WIN)
197 // Override default enumeration API and force usage of Windows MMDevice.
198 // This test will only run on Windows Vista and higher.
199 TEST_F(AudioManagerTest, EnumerateInputDevicesWinMMDevice) {
200 if (!CanRunInputTest())
201 return;
203 AudioDeviceNames device_names;
204 if (!SetMMDeviceEnumeration()) {
205 // Usage of MMDevice will fail on XP and lower.
206 LOG(WARNING) << "MM device enumeration is not supported.";
207 return;
209 audio_manager_->GetAudioInputDeviceNames(&device_names);
210 CheckDeviceNames(device_names);
213 TEST_F(AudioManagerTest, EnumerateOutputDevicesWinMMDevice) {
214 if (!CanRunOutputTest())
215 return;
217 AudioDeviceNames device_names;
218 if (!SetMMDeviceEnumeration()) {
219 // Usage of MMDevice will fail on XP and lower.
220 LOG(WARNING) << "MM device enumeration is not supported.";
221 return;
223 audio_manager_->GetAudioOutputDeviceNames(&device_names);
224 CheckDeviceNames(device_names);
227 // Override default enumeration API and force usage of Windows Wave.
228 // This test will run on Windows XP, Windows Vista and Windows 7.
229 TEST_F(AudioManagerTest, EnumerateInputDevicesWinWave) {
230 if (!CanRunInputTest())
231 return;
233 AudioDeviceNames device_names;
234 SetWaveEnumeration();
235 audio_manager_->GetAudioInputDeviceNames(&device_names);
236 CheckDeviceNames(device_names);
239 TEST_F(AudioManagerTest, EnumerateOutputDevicesWinWave) {
240 if (!CanRunOutputTest())
241 return;
243 AudioDeviceNames device_names;
244 SetWaveEnumeration();
245 audio_manager_->GetAudioOutputDeviceNames(&device_names);
246 CheckDeviceNames(device_names);
249 TEST_F(AudioManagerTest, WinXPDeviceIdUnchanged) {
250 if (!CanRunInputTest())
251 return;
253 AudioDeviceNames xp_device_names;
254 SetWaveEnumeration();
255 audio_manager_->GetAudioInputDeviceNames(&xp_device_names);
256 CheckDeviceNames(xp_device_names);
258 // Device ID should remain unchanged, including the default device ID.
259 for (AudioDeviceNames::iterator i = xp_device_names.begin();
260 i != xp_device_names.end(); ++i) {
261 EXPECT_EQ(i->unique_id,
262 GetDeviceIdFromPCMWaveInAudioInputStream(i->unique_id));
266 TEST_F(AudioManagerTest, ConvertToWinXPInputDeviceId) {
267 if (!CanRunInputTest())
268 return;
270 if (!SetMMDeviceEnumeration()) {
271 // Usage of MMDevice will fail on XP and lower.
272 LOG(WARNING) << "MM device enumeration is not supported.";
273 return;
276 AudioDeviceNames device_names;
277 audio_manager_->GetAudioInputDeviceNames(&device_names);
278 CheckDeviceNames(device_names);
280 for (AudioDeviceNames::iterator i = device_names.begin();
281 i != device_names.end(); ++i) {
282 std::string converted_id =
283 GetDeviceIdFromPCMWaveInAudioInputStream(i->unique_id);
284 if (i == device_names.begin()) {
285 // The first in the list is the default device ID, which should not be
286 // changed when passed to PCMWaveInAudioInputStream.
287 EXPECT_EQ(i->unique_id, converted_id);
288 } else {
289 // MMDevice-style device IDs should be converted to WaveIn-style device
290 // IDs.
291 EXPECT_NE(i->unique_id, converted_id);
296 #endif // defined(OS_WIN)
298 #if defined(USE_PULSEAUDIO)
299 // On Linux, there are two implementations available and both can
300 // sometimes be tested on a single system. These tests specifically
301 // test Pulseaudio.
303 TEST_F(AudioManagerTest, EnumerateInputDevicesPulseaudio) {
304 if (!CanRunInputTest())
305 return;
307 CreateAudioManagerForTesting<AudioManagerPulse>();
308 if (audio_manager_.get()) {
309 AudioDeviceNames device_names;
310 audio_manager_->GetAudioInputDeviceNames(&device_names);
311 CheckDeviceNames(device_names);
312 } else {
313 LOG(WARNING) << "No pulseaudio on this system.";
317 TEST_F(AudioManagerTest, EnumerateOutputDevicesPulseaudio) {
318 if (!CanRunOutputTest())
319 return;
321 CreateAudioManagerForTesting<AudioManagerPulse>();
322 if (audio_manager_.get()) {
323 AudioDeviceNames device_names;
324 audio_manager_->GetAudioOutputDeviceNames(&device_names);
325 CheckDeviceNames(device_names);
326 } else {
327 LOG(WARNING) << "No pulseaudio on this system.";
330 #endif // defined(USE_PULSEAUDIO)
332 #if defined(USE_ALSA)
333 // On Linux, there are two implementations available and both can
334 // sometimes be tested on a single system. These tests specifically
335 // test Alsa.
337 TEST_F(AudioManagerTest, EnumerateInputDevicesAlsa) {
338 if (!CanRunInputTest())
339 return;
341 DVLOG(2) << "Testing AudioManagerAlsa.";
342 CreateAudioManagerForTesting<AudioManagerAlsa>();
343 AudioDeviceNames device_names;
344 audio_manager_->GetAudioInputDeviceNames(&device_names);
345 CheckDeviceNames(device_names);
348 TEST_F(AudioManagerTest, EnumerateOutputDevicesAlsa) {
349 if (!CanRunOutputTest())
350 return;
352 DVLOG(2) << "Testing AudioManagerAlsa.";
353 CreateAudioManagerForTesting<AudioManagerAlsa>();
354 AudioDeviceNames device_names;
355 audio_manager_->GetAudioOutputDeviceNames(&device_names);
356 CheckDeviceNames(device_names);
358 #endif // defined(USE_ALSA)
360 TEST_F(AudioManagerTest, GetDefaultOutputStreamParameters) {
361 #if defined(OS_WIN) || defined(OS_MACOSX)
362 if (!CanRunInputTest())
363 return;
365 AudioParameters params = audio_manager_->GetDefaultOutputStreamParameters();
366 EXPECT_TRUE(params.IsValid());
367 #endif // defined(OS_WIN) || defined(OS_MACOSX)
370 TEST_F(AudioManagerTest, GetAssociatedOutputDeviceID) {
371 #if defined(OS_WIN) || defined(OS_MACOSX)
372 if (!CanRunInputTest() || !CanRunOutputTest())
373 return;
375 AudioDeviceNames device_names;
376 audio_manager_->GetAudioInputDeviceNames(&device_names);
377 bool found_an_associated_device = false;
378 for (AudioDeviceNames::iterator it = device_names.begin();
379 it != device_names.end();
380 ++it) {
381 EXPECT_FALSE(it->unique_id.empty());
382 EXPECT_FALSE(it->device_name.empty());
383 std::string output_device_id(
384 audio_manager_->GetAssociatedOutputDeviceID(it->unique_id));
385 if (!output_device_id.empty()) {
386 DVLOG(2) << it->unique_id << " matches with " << output_device_id;
387 found_an_associated_device = true;
391 EXPECT_TRUE(found_an_associated_device);
392 #endif // defined(OS_WIN) || defined(OS_MACOSX)
395 } // namespace media