// Copyright 2016 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 "lib/media/transport/shared_buffer_set_allocator.h"

#include <vector>

#include "gtest/gtest.h"

namespace media {
namespace {

static const uint64_t kSmallAlloc = 100;
static const uint64_t kLargeAlloc = 256 * 1024;

uint32_t VerifyBufferAdd(SharedBufferSetAllocator* under_test) {
  uint32_t buffer_id;
  zx::vmo vmo;
  EXPECT_TRUE(under_test->PollForBufferUpdate(&buffer_id, &vmo));
  EXPECT_TRUE(vmo);
  return buffer_id;
}

void VerifyNoBufferUpdate(SharedBufferSetAllocator* under_test) {
  uint32_t buffer_id;
  zx::vmo vmo;
  EXPECT_FALSE(under_test->PollForBufferUpdate(&buffer_id, &vmo));
}

void* AllocateRegion(SharedBufferSetAllocator* under_test, uint64_t size,
                     uint32_t* new_buffer_id_out) {
  // Do an allocation.
  void* region = under_test->AllocateRegion(size);
  EXPECT_TRUE(region);

  *new_buffer_id_out = VerifyBufferAdd(under_test);

  // Make sure no additional buffer was created unexpectedly.
  VerifyNoBufferUpdate(under_test);

  SharedBufferSet::Locator locator = under_test->LocatorFromPtr(region);
  EXPECT_EQ(*new_buffer_id_out, locator.buffer_id());

  return region;
}

void* AllocateRegion(SharedBufferSetAllocator* under_test, uint64_t size,
                     uint32_t expected_existing_buffer) {
  // Do an allocation.
  void* region = under_test->AllocateRegion(size);
  EXPECT_TRUE(region);

  // Make sure no buffer was created unexpectedly.
  VerifyNoBufferUpdate(under_test);

  SharedBufferSet::Locator locator = under_test->LocatorFromPtr(region);
  EXPECT_EQ(expected_existing_buffer, locator.buffer_id());

  return region;
}

void AllocateRegionShouldFail(SharedBufferSetAllocator* under_test,
                              uint64_t size) {
  // Do an allocation.
  void* region = under_test->AllocateRegion(size);
  EXPECT_FALSE(region);

  // Make sure no buffer was created unexpectedly.
  VerifyNoBufferUpdate(under_test);
}

uint32_t VerifyBufferRemove(SharedBufferSetAllocator* under_test,
                            uint32_t expected_buffer_id) {
  uint32_t buffer_id;
  zx::vmo vmo;
  EXPECT_TRUE(under_test->PollForBufferUpdate(&buffer_id, &vmo));
  EXPECT_EQ(expected_buffer_id, buffer_id);
  EXPECT_FALSE(vmo);
  return buffer_id;
}

// Tests SharedBufferSetAllocator::AllocateRegion and ReleaseRegion for small
// allocations.
TEST(SharedBufferSetAllocatorTest, TwoSmallAllocations) {
  SharedBufferSetAllocator under_test(
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
      ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP);

  uint32_t buffer_id;
  void* region_0 = AllocateRegion(&under_test, kSmallAlloc, &buffer_id);
  void* region_1 = AllocateRegion(&under_test, kSmallAlloc, buffer_id);

  under_test.ReleaseRegion(region_0);
  under_test.ReleaseRegion(region_1);

  // Shouldn't see any buffer updates.
  VerifyNoBufferUpdate(&under_test);
}

// Tests SharedBufferSetAllocator::AllocateRegion and ReleaseRegion for large
// allocations.
TEST(SharedBufferSetAllocatorTest, TwoLargeAllocations) {
  SharedBufferSetAllocator under_test(
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
      ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP);

  uint32_t buffer_id_0;
  void* region_0 = AllocateRegion(&under_test, kLargeAlloc, &buffer_id_0);

  uint32_t buffer_id_1;
  void* region_1 = AllocateRegion(&under_test, kLargeAlloc, &buffer_id_1);

  under_test.ReleaseRegion(region_0);
  under_test.ReleaseRegion(region_1);

  // Shouldn't see any buffer updates.
  VerifyNoBufferUpdate(&under_test);
}

// Tests SharedBufferSetAllocator::AllocateRegion and ReleaseRegion for small
// allocations that require a new buffer.
TEST(SharedBufferSetAllocatorTest, ManySmallAllocations) {
  SharedBufferSetAllocator under_test(
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
      ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP);

  std::vector<void*> first_buffer_allocations;
  uint32_t first_buffer_id;
  uint32_t second_buffer_id;

  first_buffer_allocations.push_back(
      AllocateRegion(&under_test, kSmallAlloc, &first_buffer_id));

  // Allocate small regions until a new buffer is required.
  while (true) {
    void* region = under_test.AllocateRegion(kSmallAlloc);

    uint32_t buffer_id;
    zx::vmo vmo;
    if (under_test.PollForBufferUpdate(&buffer_id, &vmo)) {
      EXPECT_TRUE(vmo);
      EXPECT_NE(first_buffer_id, buffer_id);
      second_buffer_id = buffer_id;
      SharedBufferSet::Locator locator = under_test.LocatorFromPtr(region);
      EXPECT_EQ(second_buffer_id, locator.buffer_id());
      break;
    } else {
      SharedBufferSet::Locator locator = under_test.LocatorFromPtr(region);
      EXPECT_EQ(first_buffer_id, locator.buffer_id());
      first_buffer_allocations.push_back(region);
      // We shouldn't have to allocate a lot before a buffer transition.
      EXPECT_GT(1000u, first_buffer_allocations.size());
    }
  }

  // Release regions from the first buffer and verify that the buffer is
  // removed.
  while (true) {
    under_test.ReleaseRegion(first_buffer_allocations.back());
    first_buffer_allocations.pop_back();
    if (first_buffer_allocations.empty()) {
      VerifyBufferRemove(&under_test, first_buffer_id);
      break;
    } else {
      VerifyNoBufferUpdate(&under_test);
    }
  }

  // Do another allocation from the new buffer.
  AllocateRegion(&under_test, kSmallAlloc, second_buffer_id);
}

// Tests SharedBufferSetAllocator::SetFixedBufferSize.
TEST(SharedBufferSetAllocatorTest, SetFixedBufferSize) {
  SharedBufferSetAllocator under_test(
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
      ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP);

  EXPECT_TRUE(under_test.SetFixedBufferSize(kSmallAlloc * 3));
  uint32_t buffer_id = VerifyBufferAdd(&under_test);

  void* region_0 = AllocateRegion(&under_test, kSmallAlloc, buffer_id);
  void* region_1 = AllocateRegion(&under_test, kSmallAlloc, buffer_id);
  void* region_2 = AllocateRegion(&under_test, kSmallAlloc, buffer_id);
  AllocateRegionShouldFail(&under_test, kSmallAlloc);

  under_test.ReleaseRegion(region_0);
  void* region_3 = AllocateRegion(&under_test, kSmallAlloc, buffer_id);
  AllocateRegionShouldFail(&under_test, kSmallAlloc);

  under_test.ReleaseRegion(region_1);
  under_test.ReleaseRegion(region_2);
  under_test.ReleaseRegion(region_3);

  // Shouldn't see any buffer updates.
  VerifyNoBufferUpdate(&under_test);
}

}  // namespace
}  // namespace media
