// Copyright (c) 2017 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/audio_input_device.h"

#include <utility>

#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/sync_socket.h"
#include "base/test/scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gmock_mutant.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::CancelableSyncSocket;
using base::SyncSocket;
using testing::_;
using testing::DoAll;
using testing::Invoke;
using testing::InvokeWithoutArgs;

namespace media {

namespace {

const size_t kMemorySegmentCount = 10u;

class MockAudioInputIPC : public AudioInputIPC {
 public:
  MockAudioInputIPC() = default;
  ~MockAudioInputIPC() override = default;

  MOCK_METHOD4(CreateStream,
               void(AudioInputIPCDelegate* delegate,
                    const AudioParameters& params,
                    bool automatic_gain_control,
                    uint32_t total_segments));
  MOCK_METHOD0(RecordStream, void());
  MOCK_METHOD1(SetVolume, void(double volume));
  MOCK_METHOD1(SetOutputDeviceForAec, void(const std::string&));
  MOCK_METHOD0(CloseStream, void());
};

class MockCaptureCallback : public AudioCapturerSource::CaptureCallback {
 public:
  MockCaptureCallback() = default;
  ~MockCaptureCallback() override = default;

  MOCK_METHOD0(OnCaptureStarted, void());
  MOCK_METHOD4(Capture,
               void(const AudioBus* audio_source,
                    int audio_delay_milliseconds,
                    double volume,
                    bool key_pressed));

  MOCK_METHOD1(OnCaptureError, void(const std::string& message));
  MOCK_METHOD1(OnCaptureMuted, void(bool is_muted));
};

}  // namespace.

// Regular construction.
TEST(AudioInputDeviceTest, Noop) {
  base::MessageLoopForIO io_loop;
  MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
  scoped_refptr<AudioInputDevice> device(new AudioInputDevice(
      base::WrapUnique(input_ipc), AudioInputDevice::Purpose::kUserInput));
}

ACTION_P(ReportStateChange, device) {
  static_cast<AudioInputIPCDelegate*>(device)->OnError();
}

// Verify that we get an OnCaptureError() callback if CreateStream fails.
TEST(AudioInputDeviceTest, FailToCreateStream) {
  AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                         CHANNEL_LAYOUT_STEREO, 48000, 480);

  MockCaptureCallback callback;
  MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
  scoped_refptr<AudioInputDevice> device(new AudioInputDevice(
      base::WrapUnique(input_ipc), AudioInputDevice::Purpose::kUserInput));
  device->Initialize(params, &callback);
  EXPECT_CALL(*input_ipc, CreateStream(_, _, _, _))
      .WillOnce(ReportStateChange(device.get()));
  EXPECT_CALL(callback, OnCaptureError(_));
  device->Start();
  device->Stop();
}

TEST(AudioInputDeviceTest, CreateStream) {
  AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                         CHANNEL_LAYOUT_STEREO, 48000, 480);
  base::MappedReadOnlyRegion shared_memory;
  CancelableSyncSocket browser_socket;
  CancelableSyncSocket renderer_socket;

  const uint32_t memory_size =
      media::ComputeAudioInputBufferSize(params, kMemorySegmentCount);

  shared_memory = base::ReadOnlySharedMemoryRegion::Create(memory_size);
  ASSERT_TRUE(shared_memory.IsValid());
  memset(shared_memory.mapping.memory(), 0xff, memory_size);

  ASSERT_TRUE(
      CancelableSyncSocket::CreatePair(&browser_socket, &renderer_socket));
  SyncSocket::TransitDescriptor audio_device_socket_descriptor;
  ASSERT_TRUE(renderer_socket.PrepareTransitDescriptor(
      base::GetCurrentProcessHandle(), &audio_device_socket_descriptor));
  base::ReadOnlySharedMemoryRegion duplicated_shared_memory_region =
      shared_memory.region.Duplicate();
  ASSERT_TRUE(duplicated_shared_memory_region.IsValid());

  base::test::ScopedTaskEnvironment ste;
  MockCaptureCallback callback;
  MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
  scoped_refptr<AudioInputDevice> device(new AudioInputDevice(
      base::WrapUnique(input_ipc), AudioInputDevice::Purpose::kUserInput));
  device->Initialize(params, &callback);

  EXPECT_CALL(*input_ipc, CreateStream(_, _, _, _))
      .WillOnce(InvokeWithoutArgs([&]() {
        static_cast<AudioInputIPCDelegate*>(device.get())
            ->OnStreamCreated(
                std::move(duplicated_shared_memory_region),
                SyncSocket::UnwrapHandle(audio_device_socket_descriptor),
                false);
      }));
  EXPECT_CALL(*input_ipc, RecordStream());

  EXPECT_CALL(callback, OnCaptureStarted());
  device->Start();
  EXPECT_CALL(*input_ipc, CloseStream());
  device->Stop();
}

}  // namespace media.
