// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/mac/audio_device_listener_mac.h"

#include <CoreAudio/AudioHardware.h>

#include <memory>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "media/base/bind_to_current_loop.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

class AudioDeviceListenerMacTest : public testing::Test {
 public:
  AudioDeviceListenerMacTest() {
    // It's important to create the device listener from the message loop in
    // order to ensure we don't end up with unbalanced TaskObserver calls.
    task_environment_.GetMainThreadTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&AudioDeviceListenerMacTest::CreateDeviceListener,
                       base::Unretained(this)));
    base::RunLoop().RunUntilIdle();
  }

  AudioDeviceListenerMacTest(const AudioDeviceListenerMacTest&) = delete;
  AudioDeviceListenerMacTest& operator=(const AudioDeviceListenerMacTest&) =
      delete;

  virtual ~AudioDeviceListenerMacTest() {
    // It's important to destroy the device listener from the message loop in
    // order to ensure we don't end up with unbalanced TaskObserver calls.
    task_environment_.GetMainThreadTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&AudioDeviceListenerMacTest::DestroyDeviceListener,
                       base::Unretained(this)));
    base::RunLoop().RunUntilIdle();
  }

  void CreateDeviceListener() {
    // Force a post task using BindToCurrentLoop() to ensure device listener
    // internals are working correctly.
    device_listener_ = std::make_unique<AudioDeviceListenerMac>(
        BindToCurrentLoop(
            base::BindRepeating(&AudioDeviceListenerMacTest::OnDeviceChange,
                                base::Unretained(this))),
        true /* monitor_default_input */, true /* monitor_addition_removal */);
  }

  void DestroyDeviceListener() { device_listener_.reset(); }

  bool ListenerIsValid() { return !device_listener_->listener_cb_.is_null(); }

  bool SimulateEvent(const AudioObjectPropertyAddress& address) {
    // Include multiple addresses to ensure only a single device change event
    // occurs.
    const AudioObjectPropertyAddress addresses[] = {
        address,
        {kAudioHardwarePropertySleepingIsAllowed,
         kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster}};

    OSStatus status = device_listener_->OnEvent(
        kAudioObjectSystemObject, 2, addresses,
        device_listener_->default_output_listener_.get());
    if (status != noErr)
      return false;

    device_listener_->OnEvent(kAudioObjectSystemObject, 2, addresses,
                              device_listener_->default_input_listener_.get());
    if (status != noErr)
      return false;

    device_listener_->OnEvent(
        kAudioObjectSystemObject, 2, addresses,
        device_listener_->addition_removal_listener_.get());
    return status == noErr;
  }

  bool SimulateDefaultOutputDeviceChange() {
    return SimulateEvent(
        AudioDeviceListenerMac::kDefaultOutputDeviceChangePropertyAddress);
  }

  bool SimulateDefaultInputDeviceChange() {
    return SimulateEvent(
        AudioDeviceListenerMac::kDefaultInputDeviceChangePropertyAddress);
  }

  bool SimulateDeviceAdditionRemoval() {
    return SimulateEvent(AudioDeviceListenerMac::kDevicesPropertyAddress);
  }

  MOCK_METHOD0(OnDeviceChange, void());

 protected:
  base::test::SingleThreadTaskEnvironment task_environment_;
  std::unique_ptr<AudioDeviceListenerMac> device_listener_;
};

// Simulate a device change event and ensure we get the right callback.
TEST_F(AudioDeviceListenerMacTest, Events) {
  ASSERT_TRUE(ListenerIsValid());
  EXPECT_CALL(*this, OnDeviceChange()).Times(1);
  ASSERT_TRUE(SimulateDefaultOutputDeviceChange());
  base::RunLoop().RunUntilIdle();

  EXPECT_CALL(*this, OnDeviceChange()).Times(1);
  ASSERT_TRUE(SimulateDefaultInputDeviceChange());
  base::RunLoop().RunUntilIdle();

  EXPECT_CALL(*this, OnDeviceChange()).Times(1);
  ASSERT_TRUE(SimulateDeviceAdditionRemoval());
  base::RunLoop().RunUntilIdle();
}

}  // namespace media
