// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_allocator/sync_allocator_testing.h"

#include <cstdint>

#include "pw_containers/vector.h"
#include "pw_status/status_with_size.h"
#include "pw_thread/yield.h"

// TODO: https://pwbug.dev/365161669 - Express joinability as a build-system
// constraint.
#if PW_THREAD_JOINING_ENABLED

namespace pw::allocator::test {
namespace {

using ::pw::allocator::Layout;

static constexpr size_t kNumAllocations = 128;
static constexpr size_t kSize = 64;
static constexpr size_t kAlignment = 4;

/// Tracks allocation and exercises their usable space.
struct Allocation {
  void* ptr;
  Layout layout;

  /// Fills a valid allocation with a pattern of data.
  void Paint() {
    if (ptr != nullptr) {
      auto* u8 = static_cast<uint8_t*>(ptr);
      for (size_t i = 0; i < layout.size(); ++i) {
        u8[i] = static_cast<uint8_t>(i & 0xFF);
      }
    }
  }

  /// Checks that a valid allocation has been properly `Paint`ed. Returns the
  /// first index where the expected pattern doesn't match, e.g. where memory
  /// has been corrupted, or `layout.size()` if the memory is all correct.
  size_t Inspect() const {
    if (ptr != nullptr) {
      auto* u8 = static_cast<uint8_t*>(ptr);
      for (size_t i = 0; i < layout.size(); ++i) {
        if (u8[i] != (i & 0xFF)) {
          return i;
        }
      }
    }
    return layout.size();
  }
};

}  // namespace

// BackgroundThreadCore methods.

BackgroundThreadCore::~BackgroundThreadCore() { Stop(); }

void BackgroundThreadCore::Stop() { semaphore_.release(); }

void BackgroundThreadCore::Await() {
  semaphore_.acquire();
  semaphore_.release();
}

void BackgroundThreadCore::Run() {
  while (!semaphore_.try_acquire() && RunOnce()) {
    pw::this_thread::yield();
  }
  semaphore_.release();
}

// Background methods.

Background::Background(BackgroundThreadCore& core) : core_(core) {
  thread_ = pw::Thread(context_.options(), core_);
}

Background::~Background() {
  core_.Stop();
  Await();
}

void Background::Await() {
  core_.Await();
  if (thread_.joinable()) {
    thread_.join();
  }
}

// SyncAllocatorTest unit test methods.

void SyncAllocatorTest::TestGetCapacity(size_t capacity) {
  pw::Allocator& allocator = GetAllocator();
  Background background(GetCore());

  pw::StatusWithSize actual = allocator.GetCapacity();
  EXPECT_EQ(actual.status(), pw::OkStatus());
  EXPECT_EQ(actual.size(), capacity);
}

void SyncAllocatorTest::TestAllocate() {
  pw::Allocator& allocator = GetAllocator();
  Background background(GetCore());

  pw::Vector<Allocation, kNumAllocations> allocations;
  while (!allocations.full()) {
    Layout layout(kSize, kAlignment);
    void* ptr = allocator.Allocate(layout);
    if (ptr == nullptr) {
      break;
    }
    Allocation allocation{ptr, layout};
    allocation.Paint();
    allocations.push_back(allocation);
    pw::this_thread::yield();
  }

  for (const auto& allocation : allocations) {
    EXPECT_EQ(allocation.Inspect(), allocation.layout.size());
    allocator.Deallocate(allocation.ptr);
  }
}

void SyncAllocatorTest::TestResize() {
  pw::Allocator& allocator = GetAllocator();
  Background background(GetCore());

  pw::Vector<Allocation, kNumAllocations> allocations;
  while (!allocations.full()) {
    Layout layout(kSize, kAlignment);
    void* ptr = allocator.Allocate(layout);
    Allocation allocation{ptr, layout};
    allocation.Paint();
    allocations.push_back(allocation);
    pw::this_thread::yield();
  }

  // First, resize them smaller.
  for (auto& allocation : allocations) {
    EXPECT_EQ(allocation.Inspect(), allocation.layout.size());
    size_t new_size = allocation.layout.size() / 2;
    if (!allocator.Resize(allocation.ptr, new_size)) {
      continue;
    }
    allocation.layout = Layout(new_size, allocation.layout.alignment());
    allocation.Paint();
    pw::this_thread::yield();
  }

  // Then, resize them back to their original size.
  for (auto& allocation : allocations) {
    EXPECT_EQ(allocation.Inspect(), allocation.layout.size());
    size_t old_size = allocation.layout.size() * 2;
    if (!allocator.Resize(allocation.ptr, old_size)) {
      continue;
    }
    allocation.layout = Layout(old_size, allocation.layout.alignment());
    allocation.Paint();
    pw::this_thread::yield();
  }

  for (const auto& allocation : allocations) {
    EXPECT_EQ(allocation.Inspect(), allocation.layout.size());
    allocator.Deallocate(allocation.ptr);
  }
}

void SyncAllocatorTest::TestReallocate() {
  pw::Allocator& allocator = GetAllocator();
  Background background(GetCore());

  pw::Vector<Allocation, kNumAllocations> allocations;
  while (!allocations.full()) {
    Layout layout(kSize, kAlignment);
    void* ptr = allocator.Allocate(layout);
    Allocation allocation{ptr, layout};
    allocation.Paint();
    allocations.push_back(allocation);
    pw::this_thread::yield();
  }

  for (auto& allocation : allocations) {
    EXPECT_EQ(allocation.Inspect(), allocation.layout.size());
    Layout new_layout = allocation.layout.Extend(1);
    void* new_ptr = allocator.Reallocate(allocation.ptr, new_layout);
    if (new_ptr == nullptr) {
      continue;
    }
    allocation.ptr = new_ptr;
    allocation.layout = new_layout;
    allocation.Paint();
    pw::this_thread::yield();
  }

  for (const auto& allocation : allocations) {
    EXPECT_EQ(allocation.Inspect(), allocation.layout.size());
    allocator.Deallocate(allocation.ptr);
  }
}

}  // namespace pw::allocator::test

#endif  // PW_THREAD_JOINING_ENABLED
