// 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 "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 "media/audio/audio_input_device.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::SharedMemory;
using base::SyncSocket;
using testing::_;
using testing::DoAll;
using testing::Invoke;

namespace media {

namespace {

const size_t kMemorySegmentCount = 10u;

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

  MOCK_METHOD5(CreateStream,
               void(AudioInputIPCDelegate* delegate,
                    int session_id,
                    const AudioParameters& params,
                    bool automatic_gain_control,
                    uint32_t total_segments));
  MOCK_METHOD0(RecordStream, void());
  MOCK_METHOD1(SetVolume, void(double volume));
  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));
};

// Used to terminate a loop from a different thread than the loop belongs to.
// |task_runner| should be a SingleThreadTaskRunner.
ACTION_P(QuitLoop, task_runner) {
  task_runner->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

}  // 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), io_loop.task_runner()));
}

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, 16, 480);

  base::MessageLoopForIO io_loop;
  MockCaptureCallback callback;
  MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
  scoped_refptr<AudioInputDevice> device(
      new AudioInputDevice(base::WrapUnique(input_ipc), io_loop.task_runner()));
  device->Initialize(params, &callback, 1);
  device->Start();
  EXPECT_CALL(*input_ipc, CreateStream(_, _, _, _, _))
      .WillOnce(ReportStateChange(device.get()));
  EXPECT_CALL(callback, OnCaptureError(_))
      .WillOnce(QuitLoop(io_loop.task_runner()));
  base::RunLoop().Run();
  device->Stop();
  base::RunLoop().RunUntilIdle();
}

ACTION_P3(ReportOnStreamCreated, device, handle, socket) {
  static_cast<AudioInputIPCDelegate*>(device)->OnStreamCreated(handle, socket,
                                                               false);
}

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

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

  ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size));
  memset(shared_memory.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::SharedMemoryHandle duplicated_memory_handle =
      shared_memory.handle().Duplicate();
  ASSERT_TRUE(duplicated_memory_handle.IsValid());

  base::MessageLoopForIO io_loop;
  MockCaptureCallback callback;
  MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
  scoped_refptr<AudioInputDevice> device(
      new AudioInputDevice(base::WrapUnique(input_ipc), io_loop.task_runner()));
  device->Initialize(params, &callback, 1);
  device->Start();

  EXPECT_CALL(*input_ipc, CreateStream(_, _, _, _, _))
      .WillOnce(ReportOnStreamCreated(
          device.get(), duplicated_memory_handle,
          SyncSocket::UnwrapHandle(audio_device_socket_descriptor)));
  EXPECT_CALL(*input_ipc, RecordStream());
  EXPECT_CALL(callback, OnCaptureStarted())
      .WillOnce(QuitLoop(io_loop.task_runner()));
  base::RunLoop().Run();
  device->Stop();
  base::RunLoop().RunUntilIdle();
  duplicated_memory_handle.Close();
}

}  // namespace media.
