// Copyright 2019 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.

#ifndef SRC_DEVICES_TESTING_FAKE_OBJECT_INCLUDE_LIB_FAKE_OBJECT_OBJECT_H_
#define SRC_DEVICES_TESTING_FAKE_OBJECT_INCLUDE_LIB_FAKE_OBJECT_OBJECT_H_

#include <lib/zx/status.h>
#include <limits.h>
#include <stdio.h>
#include <zircon/compiler.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <vector>

#include <fbl/auto_lock.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>

#define FAKE_OBJECT_TRACE 0
#if FAKE_OBJECT_TRACE
#define ftracef(...)                           \
  {                                            \
    printf("fake-object %16.16s: ", __func__); \
    printf(__VA_ARGS__);                       \
  }
#else
#define ftracef(...) ;
#endif

namespace fake_object {

enum class HandleType : uint32_t {
  BASE,  // A non-derived object, used for tests and assertions.
  BTI,
  MSI,
  PMT,
  RESOURCE,
  CUSTOM,  // For local tests that are not providing a fake-* lib
};

class Object : public fbl::RefCounted<Object> {
 public:
  // For each object-related syscall we stub out a fake-specific version that
  // can be implemented within the derived fake objects. syscall symbols defined
  // in the fake-object source will route to the fake impl or real impl
  // depending on the handle's validity.
  virtual zx_status_t get_child(zx_handle_t /* handle */, uint64_t /* koid */,
                                zx_rights_t /* rights */, zx_handle_t* /* out */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t get_info(zx_handle_t /* handle */, uint32_t /* topic */, void* /* buffer */,
                               size_t /* buffer_size */, size_t* /* actual_count */,
                               size_t* /* aval_count */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t get_property(zx_handle_t /* handle */, uint32_t /* property */,
                                   void* /* value */, size_t /* value_size */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t set_profile(zx_handle_t /* handle */, zx_handle_t /* profile */,
                                  uint32_t /* options */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t set_property(zx_handle_t /* handle */, uint32_t /* property */,
                                   const void* /* value */, size_t /* value_size */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t signal(zx_handle_t /* handle */, uint32_t /* clear_mask */,
                             uint32_t /* set_mask */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t signal_peer(zx_handle_t /* handle */, uint32_t /* clear_mask */,
                                  uint32_t /* set_mask */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual zx_status_t wait_one(zx_handle_t /* handle */, zx_signals_t /* signals */,
                               zx_time_t /* deadline */, zx_signals_t* /* observed */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  // |zx_object_wait_many| is omitted because we would need to define what it means to wait on
  // both real objects and fake objects at the same time due to it taking a handle table parameter.

  virtual zx_status_t wait_async(zx_handle_t /* handle */, zx_handle_t /* port */,
                                 uint64_t /* key */, zx_signals_t /* signals */,
                                 uint32_t /* options */) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  virtual ~Object() = default;

  // For the purposes of tests we only need to ensure the koid is unique to the object.
  zx_koid_t get_koid() const { return reinterpret_cast<zx_koid_t>(this); }
  virtual HandleType type() const { return HandleType::BASE; }
};

class HandleTable {
 public:
  HandleTable() = default;
  ~HandleTable() = default;

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

  // A valid fake handle does not have the reserved bits of a real handle set, and
  // has a non-zero value after shifting. This ensures that they will not overlap
  // with real handles, and that ZX_HANDLE_INVALID is not a valid fake handle.
  static bool IsValidFakeHandle(zx_handle_t handle) {
    return ((handle & ZX_HANDLE_FIXED_BITS_MASK) == 0) && (handle & ~ZX_HANDLE_FIXED_BITS_MASK);
  }

  __EXPORT
  zx::status<fbl::RefPtr<Object>> Get(zx_handle_t handle) __TA_EXCLUDES(lock_) {
    fbl::AutoLock guard(&lock_);
    return GetLocked(handle);
  }

  zx::status<> Remove(zx_handle_t handle) __TA_EXCLUDES(lock_);
  zx::status<zx_handle_t> Add(fbl::RefPtr<Object> obj) __TA_EXCLUDES(lock_);
  void Clear() __TA_EXCLUDES(lock_);

  // Walks the handle table and calls |cb| on each handle that matches the
  // provided |type|. Stops walking the table when |cb| returns false.
  //
  // |cb| must NOT attempt to acquire the lock, so this method is not suitable
  // for internal methods.
  template <typename ObjectCallback>
  void ForEach(HandleType type, const ObjectCallback cb) __TA_EXCLUDES(lock_) {
    fbl::AutoLock lock(&lock_);
    for (const auto& obj : handles_) {
      if (obj && obj->type() == type) {
        if (!std::forward<const ObjectCallback>(cb)(obj.get())) {
          break;
        }
      }
    }
  }

  void Dump() __TA_EXCLUDES(lock_);
  // We use the overall size of the vector to calculate new indices
  // so to determine the occupied size we have to verify each element.
  size_t size() __TA_EXCLUDES(lock_) {
    fbl::AutoLock lock(&lock_);
    return size_locked();
  }

 private:
  __EXPORT
  zx::status<fbl::RefPtr<Object>> GetLocked(zx_handle_t handle) __TA_REQUIRES(lock_);

  size_t size_locked() __TA_REQUIRES(lock_) {
    size_t s = 0;
    for (auto& h : handles_) {
      if (h) {
        s++;
      }
    }
    return s;
  }

  // The first |ZX_HANDLE_FIXED_BITS_MASK| bits of real handle values are
  // required to be |1|. This requirement is defined both in the public handle
  // documentation and in ProcessDispatcher's implementation.
  static constexpr size_t FakeHandleShiftBitsCount() {
    size_t bits = 0;
    uint32_t val = ZX_HANDLE_FIXED_BITS_MASK;
    while (val) {
      val >>= 1;
      bits++;
    }
    return bits;
  }

  // Fake handle values start at (1 << 2) which maps to 0 in the handle table.
  static zx::status<size_t> HandleToIndex(zx_handle_t handle) {
    if (!IsValidFakeHandle(handle)) {
      return zx::error(ZX_ERR_BAD_HANDLE);
    }
    return zx::ok((handle >> FakeHandleShiftBitsCount()) - 1);
  }

  static zx_handle_t IndexToHandle(size_t idx) {
    return static_cast<zx_handle_t>((idx + 1) << FakeHandleShiftBitsCount());
  }

  fbl::Mutex lock_;
  std::vector<fbl::RefPtr<Object>> handles_ __TA_GUARDED(lock_);
};

HandleTable& FakeHandleTable();

// Creates a base object for testing handle methods.
zx::status<zx_handle_t> fake_object_create();
zx::status<zx_koid_t> fake_object_get_koid(zx_handle_t);

void* FindRealSyscall(const char* name);

}  // namespace fake_object

#define REAL_SYSCALL(name)                                                          \
  ([]() {                                                                           \
    static const auto real_syscall =                                                \
        reinterpret_cast<decltype(name)*>(fake_object::FindRealSyscall("_" #name)); \
    return real_syscall;                                                            \
  }())

#endif  // SRC_DEVICES_TESTING_FAKE_OBJECT_INCLUDE_LIB_FAKE_OBJECT_OBJECT_H_
