// 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 "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), base::ThreadPriority::REALTIME_AUDIO));
}

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), base::ThreadPriority::REALTIME_AUDIO));
  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), base::ThreadPriority::REALTIME_AUDIO));
  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.
