audio_device_listener_mac_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 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. 4 5#include <CoreAudio/AudioHardware.h> 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "media/audio/mac/audio_device_listener_mac.h" 12#include "media/base/bind_to_current_loop.h" 13#include "testing/gmock/include/gmock/gmock.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16namespace media { 17 18class AudioDeviceListenerMacTest : public testing::Test { 19 public: 20 AudioDeviceListenerMacTest() { 21 // It's important to create the device listener from the message loop in 22 // order to ensure we don't end up with unbalanced TaskObserver calls. 23 message_loop_.PostTask(FROM_HERE, base::Bind( 24 &AudioDeviceListenerMacTest::CreateDeviceListener, 25 base::Unretained(this))); 26 message_loop_.RunUntilIdle(); 27 } 28 29 virtual ~AudioDeviceListenerMacTest() { 30 // It's important to destroy the device listener from the message loop in 31 // order to ensure we don't end up with unbalanced TaskObserver calls. 32 message_loop_.PostTask(FROM_HERE, base::Bind( 33 &AudioDeviceListenerMacTest::DestroyDeviceListener, 34 base::Unretained(this))); 35 message_loop_.RunUntilIdle(); 36 } 37 38 void CreateDeviceListener() { 39 // Force a post task using BindToCurrentLoop() to ensure device listener 40 // internals are working correctly. 41 output_device_listener_.reset(new AudioDeviceListenerMac(BindToCurrentLoop( 42 base::Bind(&AudioDeviceListenerMacTest::OnDeviceChange, 43 base::Unretained(this))))); 44 } 45 46 void DestroyDeviceListener() { 47 output_device_listener_.reset(); 48 } 49 50 bool ListenerIsValid() { 51 return !output_device_listener_->listener_cb_.is_null(); 52 } 53 54 // Simulate a device change where no output devices are available. 55 bool SimulateDefaultOutputDeviceChange() { 56 // Include multiple addresses to ensure only a single device change event 57 // occurs. 58 const AudioObjectPropertyAddress addresses[] = { 59 AudioDeviceListenerMac::kDeviceChangePropertyAddress, 60 { kAudioHardwarePropertyDevices, 61 kAudioObjectPropertyScopeGlobal, 62 kAudioObjectPropertyElementMaster } 63 }; 64 65 return noErr == output_device_listener_->OnDefaultDeviceChanged( 66 kAudioObjectSystemObject, 1, addresses, output_device_listener_.get()); 67 } 68 69 MOCK_METHOD0(OnDeviceChange, void()); 70 71 protected: 72 base::MessageLoop message_loop_; 73 scoped_ptr<AudioDeviceListenerMac> output_device_listener_; 74 75 DISALLOW_COPY_AND_ASSIGN(AudioDeviceListenerMacTest); 76}; 77 78// Simulate a device change events and ensure we get the right callbacks. 79TEST_F(AudioDeviceListenerMacTest, OutputDeviceChange) { 80 ASSERT_TRUE(ListenerIsValid()); 81 EXPECT_CALL(*this, OnDeviceChange()).Times(1); 82 ASSERT_TRUE(SimulateDefaultOutputDeviceChange()); 83 message_loop_.RunUntilIdle(); 84} 85 86} // namespace media 87