blob: 1866655125371b44eb4da3e799e5e4f4d1a1e5a1 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_MOCK_MMIO_H_
#define OPENTITAN_SW_DEVICE_LIB_TESTING_MOCK_MMIO_H_
#include <stdint.h>
#include <memory>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
namespace mock_mmio {
/**
* A MockDevice represents a mock implementation of an MMIO device.
*
* MockDevice provides two mockable member functions, representing a read and a
* write at a particular offset from the base address. This class can be
* converted into a |mmio_region_t| value, which, when used in |mmio.h|
* functions like |read32()|, will map to the appropriate mock member function
* calls.
*
* To maintain sequencing, |ReadN()| and |WriteN()| should not be
* |EXPECT_CALL|'ed directly; instead, |EXPECT_READN| and |EXPECT_WRITEN| should
* be used, instead.
*
* To use this class, |-DMOCK_MMIO| must be enabled in all translation units
* using |mmio.h|.
*/
class MockDevice {
public:
MockDevice() = default;
MockDevice(const MockDevice &) = delete;
MockDevice &operator=(const MockDevice &) = delete;
MockDevice(MockDevice &&) = delete;
MockDevice &operator=(MockDevice &&) = delete;
/**
* Converts this MockDevice into a mmio_region_t opaque object,
* which is compatible with |mmio.h| functions.
*/
mmio_region_t region() { return {this}; }
MOCK_METHOD(uint8_t, Read8, (ptrdiff_t offset));
MOCK_METHOD(uint16_t, Read16, (ptrdiff_t offset));
MOCK_METHOD(uint32_t, Read32, (ptrdiff_t offset));
MOCK_METHOD(void, Write8, (ptrdiff_t offset, uint8_t value));
MOCK_METHOD(void, Write16, (ptrdiff_t offset, uint16_t value));
MOCK_METHOD(void, Write32, (ptrdiff_t offset, uint32_t value));
};
/**
* Conveninence fixture for creating device tests.
*
* This class should be derived by a test fixture (along with |testing::Test|)
* and used in a |TEST_F| block. Doing so will make the |EXPECT_READN| and
* |EXPECT_WRITEN| conveinence macros useable.
*
* The device being mocked can be accessed in the test body with |this->dev()|.
* |this->| is required in this case, since the name |dev| is not immediately
* visible.
*/
class MmioTest {
protected:
MockDevice &dev() { return *dev_; }
private:
std::unique_ptr<MockDevice> dev_ = std::make_unique<MockDevice>();
testing::InSequence seq_;
};
} // namespace mock_mmio
/**
* Expect a read to the device |dev| at the given offset, returning the given
* 8-bit value.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_READ8_AT(dev, offset, value) \
EXPECT_CALL(dev, Read8(offset)).WillOnce(testing::Return(value))
/**
* Expect a read to the device |dev| at the given offset, returning the given
* 16-bit value.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_READ16_AT(dev, offset, value) \
EXPECT_CALL(dev, Read16(offset)).WillOnce(testing::Return(value))
/**
* Expect a read to the device |dev| at the given offset, returning the given
* 32-bit value.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_READ32_AT(dev, offset, value) \
EXPECT_CALL(dev, Read32(offset)).WillOnce(testing::Return(value))
/**
* Expect a write to the device |dev| at the given offset with the given 8-bit
* value.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_WRITE8_AT(dev, offset, value) \
EXPECT_CALL(dev, Write8(offset, value))
/**
* Expect a write to the device |dev| at the given offset with the given 16-bit
* value.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_WRITE16_AT(dev, offset, value) \
EXPECT_CALL(dev, Write16(offset, value))
/**
* Expect a write to the device |dev| at the given offset with the given 32-bit
* value.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_WRITE32_AT(dev, offset, value) \
EXPECT_CALL(dev, Write32(offset, value))
/**
* Expect a read at the given offset, returning the given 8-bit value.
*
* This function is only available in tests using a fixture that derives
* |DeviceTest|.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_READ8(offset, value) EXPECT_READ8_AT(this->dev(), offset, value)
/**
* Expect a read at the given offset, returning the given 16-bit value.
*
* This function is only available in tests using a fixture that derives
* |DeviceTest|.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_READ16(offset, value) \
EXPECT_READ16_AT(this->dev(), offset, value)
/**
* Expect a read at the given offset, returning the given 32-bit value.
*
* This function is only available in tests using a fixture that derives
* |DeviceTest|.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_READ32(offset, value) \
EXPECT_READ32_AT(this->dev(), offset, value)
/**
* Expect a write to the given offset with the given 8-bit value.
*
* This function is only available in tests using a fixture that derives
* |DeviceTest|.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_WRITE8(offset, value) \
EXPECT_WRITE8_AT(this->dev(), offset, value);
/**
* Expect a write to the given offset with the given 16-bit value.
*
* This function is only available in tests using a fixture that derives
* |DeviceTest|.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_WRITE16(offset, value) \
EXPECT_WRITE16_AT(this->dev(), offset, value);
/**
* Expect a write to the given offset with the given 32-bit value.
*
* This function is only available in tests using a fixture that derives
* |DeviceTest|.
*
* This expectation is sequenced with all other |EXPECT_READ| and |EXPECT_WRITE|
* calls.
*/
#define EXPECT_WRITE32(offset, value) \
EXPECT_WRITE32_AT(this->dev(), offset, value);
#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_MOCK_MMIO_H_