// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/capture/video/chromeos/camera_device_delegate.h"

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/run_loop.h"
#include "base/task/bind_post_task.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "media/capture/video/chromeos/camera_buffer_factory.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/camera_hal_delegate.h"
#include "media/capture/video/chromeos/mock_camera_module.h"
#include "media/capture/video/chromeos/mock_vendor_tag_ops.h"
#include "media/capture/video/chromeos/mock_video_capture_client.h"
#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
#include "media/capture/video/mock_gpu_memory_buffer_manager.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;
using testing::A;
using testing::AtLeast;
using testing::AtMost;
using testing::Invoke;
using testing::InvokeWithoutArgs;

namespace media {

namespace {

class MockCameraDevice : public cros::mojom::Camera3DeviceOps {
 public:
  MockCameraDevice() = default;

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

  ~MockCameraDevice() override = default;

  void Initialize(
      mojo::PendingRemote<cros::mojom::Camera3CallbackOps> callback_ops,
      InitializeCallback callback) override {
    DoInitialize(std::move(callback_ops), callback);
  }
  MOCK_METHOD2(
      DoInitialize,
      void(mojo::PendingRemote<cros::mojom::Camera3CallbackOps> callback_ops,
           InitializeCallback& callback));

  void ConfigureStreams(cros::mojom::Camera3StreamConfigurationPtr config,
                        ConfigureStreamsCallback callback) override {
    DoConfigureStreams(config, callback);
  }
  MOCK_METHOD2(DoConfigureStreams,
               void(cros::mojom::Camera3StreamConfigurationPtr& config,
                    ConfigureStreamsCallback& callback));

  void ConstructDefaultRequestSettings(
      cros::mojom::Camera3RequestTemplate type,
      ConstructDefaultRequestSettingsCallback callback) override {
    DoConstructDefaultRequestSettings(type, callback);
  }
  MOCK_METHOD2(DoConstructDefaultRequestSettings,
               void(cros::mojom::Camera3RequestTemplate type,
                    ConstructDefaultRequestSettingsCallback& callback));

  void ProcessCaptureRequest(cros::mojom::Camera3CaptureRequestPtr request,
                             ProcessCaptureRequestCallback callback) override {
    DoProcessCaptureRequest(request, callback);
  }
  MOCK_METHOD2(DoProcessCaptureRequest,
               void(cros::mojom::Camera3CaptureRequestPtr& request,
                    ProcessCaptureRequestCallback& callback));

  void Dump(mojo::ScopedHandle fd) override { DoDump(fd); }
  MOCK_METHOD1(DoDump, void(mojo::ScopedHandle& fd));

  void Flush(FlushCallback callback) override { DoFlush(callback); }
  MOCK_METHOD1(DoFlush, void(FlushCallback& callback));

  void RegisterBuffer(uint64_t buffer_id,
                      cros::mojom::Camera3DeviceOps::BufferType type,
                      std::vector<mojo::ScopedHandle> fds,
                      uint32_t drm_format,
                      cros::mojom::HalPixelFormat hal_pixel_format,
                      uint32_t width,
                      uint32_t height,
                      const std::vector<uint32_t>& strides,
                      const std::vector<uint32_t>& offsets,
                      RegisterBufferCallback callback) override {}

  void Close(CloseCallback callback) override { DoClose(callback); }
  MOCK_METHOD1(DoClose, void(CloseCallback& callback));

  void ConfigureStreamsAndGetAllocatedBuffers(
      cros::mojom::Camera3StreamConfigurationPtr config,
      ConfigureStreamsAndGetAllocatedBuffersCallback callback) override {
    DoConfigureStreamsAndGetAllocatedBuffers(config, callback);
  }
  MOCK_METHOD2(DoConfigureStreamsAndGetAllocatedBuffers,
               void(cros::mojom::Camera3StreamConfigurationPtr& config,
                    ConfigureStreamsAndGetAllocatedBuffersCallback& callback));

  void SignalStreamFlush(const std::vector<uint64_t>& stream_ids) override {
    DoSignalStreamFlush(stream_ids);
  }
  MOCK_METHOD1(DoSignalStreamFlush, void(std::vector<uint64_t> stream_ids));
};

constexpr int32_t kJpegMaxBufferSize = 1024;
constexpr size_t kDefaultWidth = 1280, kDefaultHeight = 720;
constexpr int32_t kDefaultMinFrameRate = 1, kDefaultMaxFrameRate = 30;

base::flat_map<ClientType, VideoCaptureParams> GetDefaultCaptureParams() {
  VideoCaptureParams params;
  base::flat_map<ClientType, VideoCaptureParams> capture_params;
  params.requested_format = {gfx::Size(kDefaultWidth, kDefaultHeight),
                             float{kDefaultMaxFrameRate}, PIXEL_FORMAT_I420};
  capture_params[ClientType::kPreviewClient] = params;
  return capture_params;
}

}  // namespace

class CameraDeviceDelegateTest : public ::testing::Test {
 public:
  CameraDeviceDelegateTest()
      : mock_camera_device_receiver_(&mock_camera_device_),
        device_delegate_thread_("DeviceDelegateThread") {}

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

  void SetUp() override {
    VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
        &mock_gpu_memory_buffer_manager_);
    camera_hal_delegate_ = std::make_unique<CameraHalDelegate>(
        base::ThreadPool::CreateSingleThreadTaskRunner(
            {}, base::SingleThreadTaskRunnerThreadMode::DEDICATED));
    if (!camera_hal_delegate_->Init()) {
      LOG(ERROR) << "Failed to initialize CameraHalDelegate";
      camera_hal_delegate_.reset();
      return;
    }
    auto get_camera_info =
        base::BindRepeating(&CameraHalDelegate::GetCameraInfoFromDeviceId,
                            base::Unretained(camera_hal_delegate_.get()));
    camera_hal_delegate_->SetCameraModule(
        mock_camera_module_.GetPendingRemote());
  }

  void TearDown() override { camera_hal_delegate_->Reset(); }

  void AllocateDevice() {
    ASSERT_FALSE(device_delegate_thread_.IsRunning());
    ASSERT_FALSE(camera_device_delegate_);

    std::vector<VideoCaptureDeviceInfo> devices_info;
    base::RunLoop run_loop;
    camera_hal_delegate_->GetDevicesInfo(base::BindLambdaForTesting(
        [&devices_info, &run_loop](std::vector<VideoCaptureDeviceInfo> result) {
          devices_info = std::move(result);
          run_loop.Quit();
        }));
    run_loop.Run();

    ASSERT_EQ(devices_info.size(), 1u);
    device_delegate_thread_.Start();

    camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>(
        devices_info[0].descriptor, camera_hal_delegate_.get(),
        device_delegate_thread_.task_runner());
  }

  void GetNumberOfFakeCameras(
      cros::mojom::CameraModule::GetNumberOfCamerasCallback& cb) {
    std::move(cb).Run(1);
  }

  void GetFakeVendorTagOps(
      mojo::PendingReceiver<cros::mojom::VendorTagOps> vendor_tag_ops_receiver,
      cros::mojom::CameraModule::GetVendorTagOpsCallback& cb) {
    mock_vendor_tag_ops_.Bind(std::move(vendor_tag_ops_receiver));
  }

  void GetFakeCameraInfo(uint32_t camera_id,
                         cros::mojom::CameraModule::GetCameraInfoCallback& cb) {
    cros::mojom::CameraInfoPtr camera_info = cros::mojom::CameraInfo::New();
    cros::mojom::CameraMetadataPtr static_metadata =
        cros::mojom::CameraMetadata::New();

    static_metadata->entry_count = 5;
    static_metadata->entry_capacity = 5;
    static_metadata->entries =
        std::vector<cros::mojom::CameraMetadataEntryPtr>();

    cros::mojom::CameraMetadataEntryPtr entry =
        cros::mojom::CameraMetadataEntry::New();
    entry->index = 0;
    entry->tag = cros::mojom::CameraMetadataTag::
        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
    entry->type = cros::mojom::EntryType::TYPE_INT32;
    entry->count = 12;
    std::vector<int32_t> stream_configurations(entry->count);
    stream_configurations[0] = static_cast<int32_t>(
        cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
    stream_configurations[1] = kDefaultWidth;
    stream_configurations[2] = kDefaultHeight;
    stream_configurations[3] = static_cast<int32_t>(
        cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT);
    stream_configurations[4] = static_cast<int32_t>(
        cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888);
    stream_configurations[5] = kDefaultWidth;
    stream_configurations[6] = kDefaultHeight;
    stream_configurations[7] = static_cast<int32_t>(
        cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT);
    stream_configurations[8] = static_cast<int32_t>(
        cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB);
    stream_configurations[9] = kDefaultWidth;
    stream_configurations[10] = kDefaultHeight;
    stream_configurations[11] = static_cast<int32_t>(
        cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT);
    uint8_t* as_int8 = reinterpret_cast<uint8_t*>(stream_configurations.data());
    entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
    static_metadata->entries->push_back(std::move(entry));

    entry = cros::mojom::CameraMetadataEntry::New();
    entry->index = 1;
    entry->tag = cros::mojom::CameraMetadataTag::ANDROID_SENSOR_ORIENTATION;
    entry->type = cros::mojom::EntryType::TYPE_INT32;
    entry->count = 1;
    entry->data = std::vector<uint8_t>(4, 0);
    static_metadata->entries->push_back(std::move(entry));

    entry = cros::mojom::CameraMetadataEntry::New();
    entry->index = 2;
    entry->tag = cros::mojom::CameraMetadataTag::ANDROID_JPEG_MAX_SIZE;
    entry->type = cros::mojom::EntryType::TYPE_INT32;
    entry->count = 1;
    int32_t jpeg_max_size = kJpegMaxBufferSize;
    as_int8 = reinterpret_cast<uint8_t*>(&jpeg_max_size);
    entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
    static_metadata->entries->push_back(std::move(entry));

    entry = cros::mojom::CameraMetadataEntry::New();
    entry->index = 3;
    entry->tag =
        cros::mojom::CameraMetadataTag::ANDROID_REQUEST_PIPELINE_MAX_DEPTH;
    entry->type = cros::mojom::EntryType::TYPE_BYTE;
    entry->count = 1;
    uint8_t pipeline_max_depth = 1;
    entry->data.assign(&pipeline_max_depth,
                       &pipeline_max_depth + entry->count * sizeof(uint8_t));
    static_metadata->entries->push_back(std::move(entry));

    entry = cros::mojom::CameraMetadataEntry::New();
    entry->index = 4;
    entry->tag = cros::mojom::CameraMetadataTag::
        ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
    entry->type = cros::mojom::EntryType::TYPE_INT32;
    entry->count = 2;
    std::vector<int32_t> available_fps_ranges = {kDefaultMinFrameRate,
                                                 kDefaultMaxFrameRate};
    as_int8 = reinterpret_cast<uint8_t*>(available_fps_ranges.data());
    entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
    static_metadata->entries->push_back(std::move(entry));

    entry = cros::mojom::CameraMetadataEntry::New();
    entry->index = 5;
    entry->tag =
        cros::mojom::CameraMetadataTag::ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE;
    entry->type = cros::mojom::EntryType::TYPE_INT32;
    entry->count = 4;
    std::vector<int32_t> active_array_size = {0, 0, 1920, 1080};
    as_int8 = reinterpret_cast<uint8_t*>(active_array_size.data());
    entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
    static_metadata->entries->push_back(std::move(entry));

    switch (camera_id) {
      case 0:
        camera_info->facing = cros::mojom::CameraFacing::CAMERA_FACING_FRONT;
        camera_info->orientation = 0;
        camera_info->static_camera_characteristics = std::move(static_metadata);
        break;
      default:
        FAIL() << "Invalid camera id";
    }
    std::move(cb).Run(0, std::move(camera_info));
  }

  void OpenMockCameraDevice(
      int32_t camera_id,
      mojo::PendingReceiver<cros::mojom::Camera3DeviceOps> device_ops_receiver,
      base::OnceCallback<void(int32_t)>& callback) {
    mock_camera_device_receiver_.Bind(std::move(device_ops_receiver));
    std::move(callback).Run(0);
  }

  void InitializeMockCameraDevice(
      mojo::PendingRemote<cros::mojom::Camera3CallbackOps> callback_ops,
      base::OnceCallback<void(int32_t)>& callback) {
    callback_ops_.Bind(std::move(callback_ops));
    std::move(callback).Run(0);
  }

  void ConfigureFakeStreams(
      cros::mojom::Camera3StreamConfigurationPtr& config,
      base::OnceCallback<void(int32_t,
                              cros::mojom::Camera3StreamConfigurationPtr)>&
          callback) {
    ASSERT_GE(2u, config->streams.size());
    ASSERT_LT(0u, config->streams.size());
    for (size_t i = 0; i < config->streams.size(); ++i) {
      config->streams[i]->usage = 0;
      config->streams[i]->max_buffers = 1;
    }
    std::move(callback).Run(0, std::move(config));
  }

  void ConstructFakeRequestSettings(
      cros::mojom::Camera3RequestTemplate type,
      base::OnceCallback<void(cros::mojom::CameraMetadataPtr)>& callback) {
    cros::mojom::CameraMetadataPtr fake_settings =
        cros::mojom::CameraMetadata::New();
    fake_settings->entry_count = 1;
    fake_settings->entry_capacity = 1;
    fake_settings->entries = std::vector<cros::mojom::CameraMetadataEntryPtr>();
    std::move(callback).Run(std::move(fake_settings));
  }

  void ProcessCaptureRequest(cros::mojom::Camera3CaptureRequestPtr& request,
                             base::OnceCallback<void(int32_t)>& callback) {
    std::move(callback).Run(0);

    cros::mojom::Camera3NotifyMsgPtr msg = cros::mojom::Camera3NotifyMsg::New();
    msg->type = cros::mojom::Camera3MsgType::CAMERA3_MSG_SHUTTER;
    cros::mojom::Camera3ShutterMsgPtr shutter_msg =
        cros::mojom::Camera3ShutterMsg::New();
    shutter_msg->timestamp = base::TimeTicks::Now().ToInternalValue();
    msg->message = cros::mojom::Camera3NotifyMsgMessage::NewShutter(
        std::move(shutter_msg));
    callback_ops_->Notify(std::move(msg));

    cros::mojom::Camera3CaptureResultPtr result =
        cros::mojom::Camera3CaptureResult::New();
    result->frame_number = request->frame_number;
    result->result = cros::mojom::CameraMetadata::New();
    result->output_buffers = std::move(request->output_buffers);
    result->partial_result = 1;
    callback_ops_->ProcessCaptureResult(std::move(result));
  }

  void CloseMockCameraDevice(base::OnceCallback<void(int32_t)>& callback) {
    mock_camera_device_receiver_.reset();
    callback_ops_.reset();
    std::move(callback).Run(0);
  }

  void SetUpExpectationForHalDelegate() {
    EXPECT_CALL(mock_camera_module_, DoGetNumberOfCameras(_))
        .Times(1)
        .WillOnce(
            Invoke(this, &CameraDeviceDelegateTest::GetNumberOfFakeCameras));
    EXPECT_CALL(mock_camera_module_, DoSetCallbacksAssociated(_, _)).Times(1);
    EXPECT_CALL(mock_camera_module_, DoGetVendorTagOps(_, _))
        .Times(1)
        .WillOnce(Invoke(this, &CameraDeviceDelegateTest::GetFakeVendorTagOps));
    EXPECT_CALL(mock_camera_module_, DoGetCameraInfo(0, _))
        .Times(1)
        .WillOnce(Invoke(this, &CameraDeviceDelegateTest::GetFakeCameraInfo));
  }

  void SetUpExpectationUntilInitialized() {
    SetUpExpectationForHalDelegate();
    EXPECT_CALL(mock_camera_module_, DoOpenDevice(0, _, _))
        .Times(1)
        .WillOnce(
            Invoke(this, &CameraDeviceDelegateTest::OpenMockCameraDevice));
    EXPECT_CALL(mock_camera_device_, DoInitialize(_, _))
        .Times(1)
        .WillOnce(Invoke(
            this, &CameraDeviceDelegateTest::InitializeMockCameraDevice));
  }

  void SetUpExpectationUntilStreamConfigured() {
    SetUpExpectationUntilInitialized();
    EXPECT_CALL(mock_camera_device_, DoConfigureStreams(_, _))
        .Times(1)
        .WillOnce(
            Invoke(this, &CameraDeviceDelegateTest::ConfigureFakeStreams));
    EXPECT_CALL(mock_gpu_memory_buffer_manager_,
                CreateGpuMemoryBuffer(
                    _, gfx::BufferFormat::YUV_420_BIPLANAR,
                    gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE,
                    gpu::kNullSurfaceHandle, nullptr))
        .Times(1)
        .WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
                             CreateFakeGpuMemoryBuffer));
    EXPECT_CALL(
        mock_gpu_memory_buffer_manager_,
        CreateGpuMemoryBuffer(_, gfx::BufferFormat::R_8,
                              gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE,
                              gpu::kNullSurfaceHandle, nullptr))
        .Times(AtMost(1))
        .WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
                             CreateFakeGpuMemoryBuffer));
    EXPECT_CALL(mock_gpu_memory_buffer_manager_,
                CreateGpuMemoryBuffer(
                    gfx::Size(kDefaultWidth, kDefaultHeight),
                    gfx::BufferFormat::YUV_420_BIPLANAR,
                    gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE,
                    gpu::kNullSurfaceHandle, nullptr))
        .Times(1)
        .WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
                             CreateFakeGpuMemoryBuffer));
    EXPECT_CALL(mock_gpu_memory_buffer_manager_,
                CreateGpuMemoryBuffer(
                    gfx::Size(kJpegMaxBufferSize, 1), gfx::BufferFormat::R_8,
                    gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE,
                    gpu::kNullSurfaceHandle, nullptr))
        .Times(AtMost(1))
        .WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
                             CreateFakeGpuMemoryBuffer));
  }

  void SetUpExpectationUntilCapturing(
      unittest_internal::MockVideoCaptureClient* mock_client) {
    SetUpExpectationUntilStreamConfigured();
    EXPECT_CALL(mock_camera_device_, DoConstructDefaultRequestSettings(_, _))
        .Times(1)
        .WillOnce(Invoke(
            this, &CameraDeviceDelegateTest::ConstructFakeRequestSettings));
    EXPECT_CALL(*mock_client, OnStarted()).Times(1);
  }

  void SetUpExpectationForCaptureLoop() {
    EXPECT_CALL(mock_camera_device_, DoProcessCaptureRequest(_, _))
        .Times(AtLeast(1))
        .WillOnce(
            Invoke(this, &CameraDeviceDelegateTest::ProcessCaptureRequest))
        .WillRepeatedly(
            Invoke(this, &CameraDeviceDelegateTest::ProcessCaptureRequest));
  }

  void SetUpExpectationForClose() {
    EXPECT_CALL(mock_camera_device_, DoClose(_))
        .Times(1)
        .WillOnce(
            Invoke(this, &CameraDeviceDelegateTest::CloseMockCameraDevice));
  }

  void WaitForDeviceToClose() {
    base::WaitableEvent device_closed(
        base::WaitableEvent::ResetPolicy::MANUAL,
        base::WaitableEvent::InitialState::NOT_SIGNALED);
    device_delegate_thread_.task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
                                  camera_device_delegate_->GetWeakPtr(),
                                  base::BindOnce(
                                      [](base::WaitableEvent* device_closed) {
                                        device_closed->Signal();
                                      },
                                      base::Unretained(&device_closed))));
    base::TimeDelta kWaitTimeoutSecs = base::Seconds(3);
    EXPECT_TRUE(device_closed.TimedWait(kWaitTimeoutSecs));
    EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState());
  }

  unittest_internal::NiceMockVideoCaptureClient* ResetDeviceContext() {
    client_type_ = ClientType::kPreviewClient;
    auto mock_client =
        std::make_unique<unittest_internal::NiceMockVideoCaptureClient>();
    auto* client_ptr = mock_client.get();
    device_context_ = std::make_unique<CameraDeviceContext>();
    device_context_->AddClient(client_type_, std::move(mock_client));
    return client_ptr;
  }

  void ResetDevice() {
    device_context_->RemoveClient(client_type_);
    ASSERT_TRUE(device_delegate_thread_.IsRunning());
    ASSERT_TRUE(camera_device_delegate_);
    ASSERT_TRUE(device_delegate_thread_.task_runner()->DeleteSoon(
        FROM_HERE, std::move(camera_device_delegate_)));
    device_delegate_thread_.Stop();
  }

  void DoLoop() {
    run_loop_ = std::make_unique<base::RunLoop>();
    run_loop_->Run();
  }

  void QuitRunLoop() {
    VLOG(2) << "quit!";
    if (run_loop_) {
      run_loop_->Quit();
    }
  }

  CameraDeviceContext::State GetState() {
    if (camera_device_delegate_->device_context_) {
      return camera_device_delegate_->device_context_->GetState();
    } else {
      // No device context means the VCD is either not started yet or already
      // stopped.
      return CameraDeviceContext::State::kStopped;
    }
  }

 protected:
  base::test::TaskEnvironment task_environment_;
  std::unique_ptr<CameraHalDelegate> camera_hal_delegate_;
  std::unique_ptr<CameraDeviceDelegate> camera_device_delegate_;

  testing::StrictMock<unittest_internal::MockCameraModule> mock_camera_module_;
  testing::NiceMock<unittest_internal::MockVendorTagOps> mock_vendor_tag_ops_;
  unittest_internal::MockGpuMemoryBufferManager mock_gpu_memory_buffer_manager_;

  testing::StrictMock<MockCameraDevice> mock_camera_device_;
  mojo::Receiver<cros::mojom::Camera3DeviceOps> mock_camera_device_receiver_;
  mojo::Remote<cros::mojom::Camera3CallbackOps> callback_ops_;

  base::Thread device_delegate_thread_;

  std::unique_ptr<CameraDeviceContext> device_context_;
  ClientType client_type_;

 private:
  std::unique_ptr<base::RunLoop> run_loop_;
};

// Test the complete capture flow: initialize, configure stream, capture one
// frame, and close the device.
TEST_F(CameraDeviceDelegateTest, AllocateCaptureAndStop) {
  auto* mock_client = ResetDeviceContext();
  mock_client->SetFrameCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  mock_client->SetQuitCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  SetUpExpectationUntilCapturing(mock_client);
  SetUpExpectationForCaptureLoop();

  AllocateDevice();

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
                                camera_device_delegate_->GetWeakPtr(),
                                GetDefaultCaptureParams(),
                                base::Unretained(device_context_.get())));

  // Wait until a frame is received.  MockVideoCaptureClient calls QuitRunLoop()
  // to stop the run loop.
  DoLoop();
  EXPECT_EQ(CameraDeviceContext::State::kCapturing, GetState());

  SetUpExpectationForClose();

  WaitForDeviceToClose();

  ResetDevice();
}

// Test that the camera device delegate closes properly when StopAndDeAllocate()
// is called when the device is opening. The timeline is roughly:
// 1. AllocateAndStart()
// 2. Async IPC call OpenDevice() started
// 3. StopAndDeAllocate()
// 4. Async IPC call OpenDevice() finished
TEST_F(CameraDeviceDelegateTest, StopBeforeOpened) {
  auto* mock_client = ResetDeviceContext();
  mock_client->SetQuitCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  SetUpExpectationForHalDelegate();

  AllocateDevice();

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
                                camera_device_delegate_->GetWeakPtr(),
                                GetDefaultCaptureParams(),
                                base::Unretained(device_context_.get())));

  base::WaitableEvent stop_posted;
  auto open_device_quit_loop_cb =
      [&](int32_t camera_id,
          mojo::PendingReceiver<cros::mojom::Camera3DeviceOps>
              device_ops_receiver,
          base::OnceCallback<void(int32_t)>& callback) {
        QuitRunLoop();
        // Make sure StopAndDeAllocate() is called before the device opened
        // callback.
        stop_posted.Wait();
        OpenMockCameraDevice(camera_id, std::move(device_ops_receiver),
                             callback);
      };
  EXPECT_CALL(mock_camera_module_, DoOpenDevice(0, _, _))
      .Times(1)
      .WillOnce(Invoke(open_device_quit_loop_cb));

  // Wait until the QuitRunLoop() call in |mock_camera_module_->OpenDevice()|.
  DoLoop();

  SetUpExpectationForClose();

  base::WaitableEvent device_closed;
  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
                     camera_device_delegate_->GetWeakPtr(),
                     base::BindOnce(&base::WaitableEvent::Signal,
                                    base::Unretained(&device_closed))));
  stop_posted.Signal();
  EXPECT_TRUE(device_closed.TimedWait(base::Seconds(3)));
  EXPECT_EQ(CameraDeviceContext::State::kStopped, GetState());

  ResetDevice();
}

// Test that the camera device delegate closes properly when StopAndDeAllocate
// is called right after the device is initialized.
TEST_F(CameraDeviceDelegateTest, StopAfterInitialized) {
  auto* mock_client = ResetDeviceContext();
  mock_client->SetQuitCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  SetUpExpectationUntilInitialized();

  AllocateDevice();

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
                                camera_device_delegate_->GetWeakPtr(),
                                GetDefaultCaptureParams(),
                                base::Unretained(device_context_.get())));

  EXPECT_CALL(mock_camera_device_, DoConfigureStreams(_, _))
      .Times(1)
      .WillOnce(Invoke(
          [this](cros::mojom::Camera3StreamConfigurationPtr& config,
                 base::OnceCallback<void(
                     int32_t, cros::mojom::Camera3StreamConfigurationPtr)>&
                     callback) {
            EXPECT_EQ(CameraDeviceContext::State::kInitialized,
                      this->GetState());
            std::move(callback).Run(-ENODEV, {});
            this->QuitRunLoop();
          }));

  // Wait until the QuitRunLoop call in |mock_camera_device_->ConfigureStreams|.
  DoLoop();

  SetUpExpectationForClose();

  WaitForDeviceToClose();

  ResetDevice();
}

// Test that the camera device delegate closes properly when StopAndDeAllocate
// is called right after the stream is configured.
TEST_F(CameraDeviceDelegateTest, StopAfterStreamConfigured) {
  auto* mock_client = ResetDeviceContext();
  mock_client->SetQuitCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  SetUpExpectationUntilStreamConfigured();

  AllocateDevice();

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
                                camera_device_delegate_->GetWeakPtr(),
                                GetDefaultCaptureParams(),
                                base::Unretained(device_context_.get())));

  EXPECT_CALL(mock_camera_device_, DoConstructDefaultRequestSettings(_, _))
      .Times(1)
      .WillOnce(Invoke(
          [this](cros::mojom::Camera3RequestTemplate type,
                 base::OnceCallback<void(cros::mojom::CameraMetadataPtr)>&
                     callback) {
            EXPECT_EQ(CameraDeviceContext::State::kStreamConfigured,
                      this->GetState());
            std::move(callback).Run({});
            this->QuitRunLoop();
          }));

  // Wait until the QuitRunLoop call in |mock_camera_device_->ConfigureStreams|.
  DoLoop();

  SetUpExpectationForClose();

  WaitForDeviceToClose();

  ResetDevice();
}

// Test that the camera device delegate handles camera device open failures
// correctly.
TEST_F(CameraDeviceDelegateTest, FailToOpenDevice) {
  SetUpExpectationForHalDelegate();

  AllocateDevice();

  auto* mock_client = ResetDeviceContext();

  auto stop_on_error = [&]() {
    device_delegate_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
                       camera_device_delegate_->GetWeakPtr(),
                       base::BindPostTaskToCurrentDefault(base::BindOnce(
                           &CameraDeviceDelegateTest::QuitRunLoop,
                           base::Unretained(this)))));
  };
  EXPECT_CALL(*mock_client, OnError(_, _, _))
      .Times(AtLeast(1))
      .WillRepeatedly(InvokeWithoutArgs(stop_on_error));

  // Hold the |device_ops_receiver| to make the behavior of CameraDeviceDelegate
  // deterministic. Otherwise the connection error handler would race with the
  // callback of OpenDevice(), because they are in different mojo channels.
  mojo::PendingReceiver<cros::mojom::Camera3DeviceOps>
      device_ops_receiver_holder;
  auto open_device_with_error_cb =
      [&](int32_t camera_id,
          mojo::PendingReceiver<cros::mojom::Camera3DeviceOps>
              device_ops_receiver,
          base::OnceCallback<void(int32_t)>& callback) {
        device_ops_receiver_holder = std::move(device_ops_receiver);
        std::move(callback).Run(-ENODEV);
      };
  EXPECT_CALL(mock_camera_module_, DoOpenDevice(0, _, _))
      .Times(1)
      .WillOnce(Invoke(open_device_with_error_cb));

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
                                camera_device_delegate_->GetWeakPtr(),
                                GetDefaultCaptureParams(),
                                base::Unretained(device_context_.get())));

  // Wait unitl |camera_device_delegate_->StopAndDeAllocate| calls the
  // QuitRunLoop callback.
  DoLoop();

  ResetDevice();
}

// Test that the class handles it correctly when StopAndDeAllocate is called
// multiple times.
TEST_F(CameraDeviceDelegateTest, DoubleStopAndDeAllocate) {
  auto* mock_client = ResetDeviceContext();
  mock_client->SetFrameCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  mock_client->SetQuitCb(base::BindPostTaskToCurrentDefault(base::BindOnce(
      &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))));
  SetUpExpectationUntilCapturing(mock_client);
  SetUpExpectationForCaptureLoop();

  AllocateDevice();

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
                                camera_device_delegate_->GetWeakPtr(),
                                GetDefaultCaptureParams(),
                                base::Unretained(device_context_.get())));

  // Wait until a frame is received.  MockVideoCaptureClient calls QuitRunLoop()
  // to stop the run loop.
  DoLoop();

  EXPECT_EQ(CameraDeviceContext::State::kCapturing, GetState());

  SetUpExpectationForClose();

  WaitForDeviceToClose();

  device_delegate_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
                     camera_device_delegate_->GetWeakPtr(),
                     base::BindPostTaskToCurrentDefault(
                         base::BindOnce(&CameraDeviceDelegateTest::QuitRunLoop,
                                        base::Unretained(this)))));
  DoLoop();

  ResetDevice();
}

}  // namespace media
