// 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_BUS_TESTING_MOCK_SDIO_INCLUDE_LIB_MOCK_SDIO_MOCK_SDIO_H_
#define SRC_DEVICES_BUS_TESTING_MOCK_SDIO_INCLUDE_LIB_MOCK_SDIO_MOCK_SDIO_H_

#include <lib/fzl/vmo-mapper.h>

#include <ddktl/protocol/sdio.h>
#include <fbl/vector.h>
#include <zxtest/zxtest.h>

namespace mock_sdio {

// This class mocks an SDIO device by providing an sdio_protocol_t. Users can set expectations that
// either return specified data on read or verify data on write. After the test, use VerifyAndClear
// to reset the object and verify that all expectations were satisfied. See the following example
// test:
//
// mock_sdio::MockSdio sdio;
// sdio
//     .ExpectReadByte(SDIO_FN_1, 0x10, 0xab)
//     .ExpectFifoWrite(SDIO_FN_2, 0x20, {0x01, 0x23, 0x45, 0x67}, true)
//     .ExpectRead(SDIO_FN_1, 0x00, {0x89, 0xab});
//
// SomeDriver dut(sdio.GetProto());
//
// EXPECT_OK(dut.SomeMethod());
// ASSERT_NO_FATAL_FAILURES(sdio.VerifyAndClear());

class MockSdio : ddk::SdioProtocol<MockSdio> {
 public:
  MockSdio() : proto_{&sdio_protocol_ops_, this} {}

  const sdio_protocol_t* GetProto() { return &proto_; }

  MockSdio& ExpectReadByte(uint32_t addr, uint8_t byte) {
    SdioRwExpectation exp{
        .addr = addr, .incr = false, .write = false, .data = {byte}, .exact = true};
    expectations_.push_back(std::move(exp));
    return *this;
  }

  MockSdio& ExpectWriteByte(uint32_t addr, uint8_t byte) {
    SdioRwExpectation exp{
        .addr = addr, .incr = false, .write = true, .data = {byte}, .exact = true};
    expectations_.push_back(std::move(exp));
    return *this;
  }

  MockSdio& ExpectFifoRead(uint32_t addr, fbl::Vector<uint8_t> buf, bool exact) {
    SdioRwExpectation exp{
        .addr = addr, .incr = false, .write = false, .data = std::move(buf), .exact = exact};
    expectations_.push_back(std::move(exp));
    return *this;
  }

  MockSdio& ExpectFifoWrite(uint32_t addr, fbl::Vector<uint8_t> buf, bool exact) {
    SdioRwExpectation exp{
        .addr = addr, .incr = false, .write = true, .data = std::move(buf), .exact = exact};
    expectations_.push_back(std::move(exp));
    return *this;
  }

  MockSdio& ExpectRead(uint32_t addr, fbl::Vector<uint8_t> buf, bool exact) {
    SdioRwExpectation exp{
        .addr = addr, .incr = true, .write = false, .data = std::move(buf), .exact = exact};
    expectations_.push_back(std::move(exp));
    return *this;
  }

  MockSdio& ExpectWrite(uint32_t addr, fbl::Vector<uint8_t> buf, bool exact) {
    SdioRwExpectation exp{
        .addr = addr, .incr = true, .write = true, .data = std::move(buf), .exact = exact};
    expectations_.push_back(std::move(exp));
    return *this;
  }

  MockSdio& ExpectGetInBandIntr(const zx::interrupt& interrupt) {
    ExpectGetInBandIntrHelper(interrupt);
    return *this;
  }

  void VerifyAndClear() {
    EXPECT_EQ(expectations_index_, expectations_.size(), "More transactions are expected");
    expectations_.reset();
    expectations_index_ = 0;
  }

  // These are used by ddk::SdioProtocol but are not intended for use by tests.
  zx_status_t SdioGetDevHwInfo(sdio_hw_info_t* out_hw_info) { return ZX_ERR_NOT_SUPPORTED; }

  // TODO(bradenkell): Add support for testing these.
  zx_status_t SdioEnableFn() { return ZX_OK; }

  zx_status_t SdioDisableFn() { return ZX_OK; }

  zx_status_t SdioEnableFnIntr() { return ZX_OK; }

  zx_status_t SdioDisableFnIntr() { return ZX_OK; }

  zx_status_t SdioUpdateBlockSize(uint16_t blk_sz, bool deflt) { return ZX_OK; }

  zx_status_t SdioGetBlockSize(uint16_t* out_cur_blk_size) { return ZX_ERR_NOT_SUPPORTED; }

  zx_status_t SdioDoRwTxn(sdio_rw_txn_t* txn) {
    DoRwTxnHelper(txn);
    return ZX_OK;
  }

  zx_status_t SdioDoRwByte(bool write, uint32_t addr, uint8_t write_byte, uint8_t* out_read_byte) {
    DoRwByteHelper(write, addr, write_byte, out_read_byte);
    return ZX_OK;
  }

  zx_status_t SdioGetInBandIntr(zx::interrupt* out_irq) {
    GetInBandIntrHelper(out_irq);
    return ZX_OK;
  }

  zx_status_t SdioIoAbort() { return ZX_ERR_NOT_SUPPORTED; }

  zx_status_t SdioIntrPending(bool* out_pending) { return ZX_ERR_NOT_SUPPORTED; }

  zx_status_t SdioDoVendorControlRwByte(bool write, uint8_t addr, uint8_t write_byte,
                                        uint8_t* out_read_byte) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_status_t SdioRegisterVmo(uint32_t vmo_id, zx::vmo vmo, uint64_t offset, uint64_t size,
                              uint32_t vmo_rights) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  zx_status_t SdioUnregisterVmo(uint32_t vmo_id, zx::vmo* out_vmo) { return ZX_ERR_NOT_SUPPORTED; }
  zx_status_t SdioDoRwTxnNew(const sdio_rw_txn_new_t* txn) { return ZX_ERR_NOT_SUPPORTED; }
  void SdioRunDiagnostics() {}

 private:
  struct SdioRwExpectation {
    uint32_t addr;
    bool incr;
    bool write;
    fbl::Vector<uint8_t> data;
    bool exact;
  };

  void ExpectGetInBandIntrHelper(const zx::interrupt& interrupt) {
    ASSERT_FALSE(interrupt_.is_valid(), "Interrupt has already been set");
    EXPECT_OK(interrupt.duplicate(ZX_RIGHT_SAME_RIGHTS, &interrupt_),
              "Failed to duplicate interrupt");
  }

  void DoRwHelper(uint32_t addr, bool incr, bool write, uint8_t* buffer, uint32_t size) {
    ASSERT_LT(expectations_index_, expectations_.size(), "No more transactions are expected");

    const SdioRwExpectation& exp = expectations_[expectations_index_++];
    EXPECT_EQ(exp.addr, addr, "Transaction address mismatch");
    EXPECT_EQ(exp.incr, incr, "Transaction FIFO mismatch");
    ASSERT_EQ(exp.write, write, "Transaction read/write mismatch");

    if (exp.exact) {
      ASSERT_EQ(exp.data.size(), size, "Transaction size mismatch");
    } else {
      // The expected message must not be larger than the provided buffer.
      ASSERT_LE(exp.data.size(), size, "Transaction size mismatch");
    }

    if (write) {
      EXPECT_BYTES_EQ(exp.data.data(), buffer, exp.data.size());
    } else {
      memcpy(buffer, exp.data.data(), exp.data.size());
    }
  }

  void DoRwTxnHelper(sdio_rw_txn_t* txn) {
    ASSERT_NOT_NULL(txn, "Transaction struct is null");

    uint8_t* buffer = reinterpret_cast<uint8_t*>(txn->virt_buffer) + txn->buf_offset;

    fzl::VmoMapper mapper;
    if (txn->use_dma) {
      zx::vmo vmo(txn->dma_vmo);
      zx_status_t status = mapper.Map(vmo, 0, txn->data_size, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);

      __UNUSED zx_handle_t handle = vmo.release();

      ASSERT_OK(status, "Failed to map DMA VMO");

      buffer = reinterpret_cast<uint8_t*>(mapper.start()) + txn->buf_offset;
    }

    DoRwHelper(txn->addr, txn->incr, txn->write, buffer, txn->data_size);
  }

  void DoRwByteHelper(bool write, uint32_t addr, uint8_t write_byte, uint8_t* out_read_byte) {
    DoRwHelper(addr, false, write, write ? &write_byte : out_read_byte, 1);
  }

  void GetInBandIntrHelper(zx::interrupt* out_irq) {
    ASSERT_TRUE(interrupt_.is_valid(), "No interrupt has been set");
    ASSERT_NOT_NULL(out_irq, "Out interrupt is null");

    *out_irq = std::move(interrupt_);
  }

  const sdio_protocol_t proto_;
  zx::interrupt interrupt_;
  fbl::Vector<SdioRwExpectation> expectations_;
  size_t expectations_index_ = 0;
};

}  // namespace mock_sdio

#endif  // SRC_DEVICES_BUS_TESTING_MOCK_SDIO_INCLUDE_LIB_MOCK_SDIO_MOCK_SDIO_H_
