// Copyright 2020 The Fuchsia 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 "src/camera/bin/device/sysmem_allocator.h"

#include <fuchsia/sysmem/cpp/fidl_test_base.h>
#include <lib/async/cpp/executor.h>
#include <lib/fidl/cpp/binding.h>

#include "src/lib/testing/loop_fixture/test_loop_fixture.h"

namespace camera {
namespace {

class FakeBufferCollection : public fuchsia::sysmem::testing::BufferCollection_TestBase {
 public:
  FakeBufferCollection(fidl::InterfaceRequest<fuchsia::sysmem::BufferCollection> request)
      : binding_{this, std::move(request)} {}

  void PeerClose() { binding_.Unbind(); }
  void CompleteBufferAllocation(zx_status_t status,
                                fuchsia::sysmem::BufferCollectionInfo_2 collection) {
    ASSERT_TRUE(allocated_callback_);
    allocated_callback_(status, std::move(collection));
    allocated_callback_ = nullptr;
  }

 private:
  // |fuchsia::sysmem::BufferCollection|
  void Close() override { binding_.Close(ZX_OK); }
  void SetName(uint32_t priority, std::string name) override {}
  void SetConstraints(bool has_constraints,
                      fuchsia::sysmem::BufferCollectionConstraints constraints) override {}
  void WaitForBuffersAllocated(WaitForBuffersAllocatedCallback callback) override {
    allocated_callback_ = std::move(callback);
  }

  void AttachLifetimeTracking(zx::eventpair server_end, uint32_t buffers_remaining) override {
    lifetime_tracking_ = std::move(server_end);
  }

  void NotImplemented_(const std::string& name) override {
    FAIL() << "Not Implemented BufferCollection." << name;
  }

  fidl::Binding<fuchsia::sysmem::BufferCollection> binding_;
  WaitForBuffersAllocatedCallback allocated_callback_;
  zx::eventpair lifetime_tracking_;
};

class FakeAllocator : public fuchsia::sysmem::testing::Allocator_TestBase {
 public:
  fuchsia::sysmem::AllocatorHandle NewBinding() { return binding_.NewBinding(); }

  const std::vector<std::unique_ptr<FakeBufferCollection>>& bound_collections() const {
    return collections_;
  }

 private:
  // |fuchsia::sysmem::Allocator|
  void AllocateNonSharedCollection(
      fidl::InterfaceRequest<fuchsia::sysmem::BufferCollection> request) override {
    collections_.emplace_back(std::make_unique<FakeBufferCollection>(std::move(request)));
  }
  void BindSharedCollection(
      fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token,
      fidl::InterfaceRequest<fuchsia::sysmem::BufferCollection> request) override {
    collections_.emplace_back(std::make_unique<FakeBufferCollection>(std::move(request)));
  }

  void NotImplemented_(const std::string& name) override {
    FAIL() << "Not Implemented Allocator." << name;
  }

  fidl::Binding<fuchsia::sysmem::Allocator> binding_{this};
  std::vector<std::unique_ptr<FakeBufferCollection>> collections_;
};

class SysmemAllocatorTest : public gtest::TestLoopFixture {
 protected:
  FakeBufferCollection* last_bound_collection() {
    return sysmem_allocator_.bound_collections().empty()
               ? nullptr
               : sysmem_allocator_.bound_collections().back().get();
  }

  FakeAllocator sysmem_allocator_;
  SysmemAllocator allocator_{sysmem_allocator_.NewBinding()};
  async::Executor executor_{dispatcher()};
};

TEST_F(SysmemAllocatorTest, BindSharedCollection) {
  fuchsia::sysmem::BufferCollectionTokenHandle token;
  auto request = token.NewRequest();
  fit::result<BufferCollectionWithLifetime, zx_status_t> result;
  executor_.schedule_task(
      allocator_.BindSharedCollection(std::move(token), {}, "CollectionName")
          .then([&result](fit::result<BufferCollectionWithLifetime, zx_status_t>& r) mutable {
            result = std::move(r);
          }));
  RunLoopUntilIdle();

  // Now we should have the shared buffer collection.
  ASSERT_EQ(1u, sysmem_allocator_.bound_collections().size());
  last_bound_collection()->CompleteBufferAllocation(ZX_OK,
                                                    fuchsia::sysmem::BufferCollectionInfo_2{});
  RunLoopUntilIdle();
  EXPECT_TRUE(result.is_ok());
}

}  // namespace
}  // namespace camera
