[sw/silicon_creator] Make GlobalMock a base class
This change makes GlobalMock a base class for all mocks used in Mask ROM
unit tests to support multiple types of mocks, e.g. strict and nice, for
a Mask ROM module.
Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/lib/base/testing/mock_csr.h b/sw/device/lib/base/testing/mock_csr.h
index 2e119ec..f3c8282 100644
--- a/sw/device/lib/base/testing/mock_csr.h
+++ b/sw/device/lib/base/testing/mock_csr.h
@@ -14,18 +14,16 @@
namespace internal {
-class MockCsr {
+class MockCsr : public ::mask_rom_test::GlobalMock<MockCsr> {
public:
MOCK_METHOD(uint32_t, Read, (uint32_t csr));
MOCK_METHOD(void, Write, (uint32_t csr, uint32_t value));
MOCK_METHOD(void, SetBits, (uint32_t csr, uint32_t mask));
MOCK_METHOD(void, ClearBits, (uint32_t csr, uint32_t mask));
- virtual ~MockCsr() {}
};
} // namespace internal
-using MockCsr =
- ::mask_rom_test::GlobalMock<testing::StrictMock<internal::MockCsr>>;
+using MockCsr = testing::StrictMock<internal::MockCsr>;
/**
* Conveninence fixture for creating CSR tests.
diff --git a/sw/device/lib/testing/mask_rom_test.h b/sw/device/lib/testing/mask_rom_test.h
index d7dab97..4d5e473 100644
--- a/sw/device/lib/testing/mask_rom_test.h
+++ b/sw/device/lib/testing/mask_rom_test.h
@@ -11,44 +11,50 @@
namespace mask_rom_test {
/**
- * Mixin for global mocks.
+ * Base class for mocks used in Mask ROM unit tests.
*
- * `GlobalMock<T>` is a derived class of `T` that can have at most one instance
- * at a time (checked at runtime) and makes this instance globally accessible
- * via the static `GlobalMock<T> &Instance()` method.
+ * If a class `Mock` derives from `GlobalMock<Mock>`, `GlobalMock<Mock>`
+ * ensures that there is at most one instance of `Mock` at a time (checked at
+ * runtime) and makes this instance globally accessible via the static `Mock
+ * &Instance()` method.
*
- * Mock classes used in tests should be of this type so that mock functions can
- * access their instances during tests. Since we prefer using strict mocks,
- * mock classes should also be of type `testing::StrictMock`. Mock classes that
- * satisfy both requirements can be defined using a type alias as follows:
+ * Mock classes should be globally accessible so that mock functions can call
+ * their methods during tests. They can also be strict or nice depending on
+ * tests' needs. Mock classes that satisfy both requirements can be defined as
+ * follows:
*
* namespace mask_rom_test {
* namespace internal {
- * class MockFoo {
+ * class MockFoo : public GlobalMock<MockFoo> {
* ...
* };
* } // namespace internal
- * // Type alias for making `internal::MockFoo` a global and strict mock.
- * using MockFoo = GlobalMock<testing::StrictMock<internal::MockFoo>>;
+ * // Type alias for making `internal::MockFoo` a strict mock.
+ * using MockFoo = testing::StrictMock<internal::MockFoo>;
+ * // Type alias for making `internal::MockFoo` a nice mock if needed.
+ * using NiceMockFoo = testing::NiceMock<internal::MockFoo>;
* ...
* } // namespace mask_rom_test
+ *
+ * This construction also ensures that we cannot have `MockFoo` and
+ * `NiceMockFoo` instantiated at the same time since they both derive from the
+ * same class, i.e. `GlobalMock<internal::MockFoo>`.
*/
-template <typename T>
-class GlobalMock : public T {
+template <typename Mock>
+class GlobalMock {
public:
- template <typename... Args>
- GlobalMock(Args &&... args) : T(std::forward(args)...) {
+ GlobalMock() {
if (instance_ != nullptr) {
throw std::runtime_error("Mock is already instantiated.");
}
- instance_ = this;
+ instance_ = static_cast<Mock *>(this);
}
- static_assert(std::has_virtual_destructor<T>::value,
- "Mock class must have a virtual destructor.");
+ // Note: Destructors of mock classes must be virtual for `testing::StrictMock`
+ // and `testing::NiceMock` to work correctly.
virtual ~GlobalMock() { instance_ = nullptr; }
- static GlobalMock<T> &Instance() {
+ static Mock &Instance() {
if (instance_ == nullptr) {
throw std::runtime_error("Mock is not instantiated yet.");
}
@@ -61,10 +67,10 @@
GlobalMock &operator=(GlobalMock &&) = delete;
private:
- static GlobalMock<T> *instance_;
+ static Mock *instance_;
};
-template <typename T>
-GlobalMock<T> *GlobalMock<T>::instance_ = nullptr;
+template <typename Mock>
+Mock *GlobalMock<Mock>::instance_ = nullptr;
/**
* Test fixture for mask ROM tests.
diff --git a/sw/device/silicon_creator/lib/base/mock_abs_mmio.h b/sw/device/silicon_creator/lib/base/mock_abs_mmio.h
index a470e81..5b15152 100644
--- a/sw/device/silicon_creator/lib/base/mock_abs_mmio.h
+++ b/sw/device/silicon_creator/lib/base/mock_abs_mmio.h
@@ -14,18 +14,16 @@
/**
* Mock class for abs_mmio.c.
*/
-class MockAbsMmio {
+class MockAbsMmio : public GlobalMock<MockAbsMmio> {
public:
MOCK_METHOD(uint8_t, Read8, (uint32_t addr));
MOCK_METHOD(void, Write8, (uint32_t addr, uint8_t value));
MOCK_METHOD(uint32_t, Read32, (uint32_t addr));
MOCK_METHOD(void, Write32, (uint32_t addr, uint32_t value));
-
- virtual ~MockAbsMmio() {}
};
} // namespace internal
-using MockAbsMmio = GlobalMock<testing::StrictMock<internal::MockAbsMmio>>;
+using MockAbsMmio = testing::StrictMock<internal::MockAbsMmio>;
/**
* Expect a read to the device `dev` at the given offset, returning the given
diff --git a/sw/device/silicon_creator/lib/base/mock_sec_mmio.h b/sw/device/silicon_creator/lib/base/mock_sec_mmio.h
index d04ca52..4582fec 100644
--- a/sw/device/silicon_creator/lib/base/mock_sec_mmio.h
+++ b/sw/device/silicon_creator/lib/base/mock_sec_mmio.h
@@ -14,7 +14,7 @@
/**
* Mock class for abs_mmio.c.
*/
-class MockSecMmio {
+class MockSecMmio : public GlobalMock<MockSecMmio> {
public:
MOCK_METHOD(void, Init, (sec_mmio_shutdown_handler callee));
MOCK_METHOD(uint32_t, Read32, (uint32_t addr));
@@ -22,12 +22,10 @@
MOCK_METHOD(void, WriteIncrement, (uint32_t value));
MOCK_METHOD(void, CheckValues, (uint32_t rnd_offset));
MOCK_METHOD(void, CheckCounters, (uint32_t expected_check_count));
-
- virtual ~MockSecMmio() {}
};
} // namespace internal
-using MockSecMmio = GlobalMock<testing::StrictMock<internal::MockSecMmio>>;
+using MockSecMmio = testing::StrictMock<internal::MockSecMmio>;
/**
* Expect a read to the device `dev` at the given offset, returning the given
diff --git a/sw/device/silicon_creator/lib/drivers/mock_alert.h b/sw/device/silicon_creator/lib/drivers/mock_alert.h
index 897346a..2934767 100644
--- a/sw/device/silicon_creator/lib/drivers/mock_alert.h
+++ b/sw/device/silicon_creator/lib/drivers/mock_alert.h
@@ -14,7 +14,7 @@
/**
* Mock class for alert.c.
*/
-class MockAlert {
+class MockAlert : public GlobalMock<MockAlert> {
public:
MOCK_METHOD(rom_error_t, alert_configure,
(size_t, alert_class_t, alert_enable_t));
@@ -23,12 +23,11 @@
MOCK_METHOD(rom_error_t, alert_class_configure,
(alert_class_t, const alert_class_config_t *));
MOCK_METHOD(rom_error_t, alert_ping_enable, ());
- virtual ~MockAlert() {}
};
} // namespace internal
-using MockAlert = GlobalMock<testing::StrictMock<internal::MockAlert>>;
+using MockAlert = testing::StrictMock<internal::MockAlert>;
extern "C" {
diff --git a/sw/device/silicon_creator/lib/drivers/mock_hmac.h b/sw/device/silicon_creator/lib/drivers/mock_hmac.h
index a80ad0d..eeeba87 100644
--- a/sw/device/silicon_creator/lib/drivers/mock_hmac.h
+++ b/sw/device/silicon_creator/lib/drivers/mock_hmac.h
@@ -14,17 +14,16 @@
/**
* Mock class for hmac.c.
*/
-class MockHmac {
+class MockHmac : public GlobalMock<MockHmac> {
public:
MOCK_METHOD(void, sha256_init, ());
MOCK_METHOD(rom_error_t, sha256_update, (const void *, size_t));
MOCK_METHOD(rom_error_t, sha256_final, (hmac_digest_t *));
- virtual ~MockHmac() {}
};
} // namespace internal
-using MockHmac = GlobalMock<testing::StrictMock<internal::MockHmac>>;
+using MockHmac = testing::StrictMock<internal::MockHmac>;
extern "C" {
diff --git a/sw/device/silicon_creator/lib/drivers/mock_otp.h b/sw/device/silicon_creator/lib/drivers/mock_otp.h
index 25348d6..11f5d6a 100644
--- a/sw/device/silicon_creator/lib/drivers/mock_otp.h
+++ b/sw/device/silicon_creator/lib/drivers/mock_otp.h
@@ -14,20 +14,27 @@
/**
* Mock class for otp.c.
*/
-class MockOtp {
+class MockOtp : public GlobalMock<MockOtp> {
public:
MOCK_METHOD(uint32_t, read32, (uint32_t address));
MOCK_METHOD(uint32_t, read64, (uint32_t address));
MOCK_METHOD(void, read, (uint32_t address, uint32_t *data, size_t num_words));
- virtual ~MockOtp() {}
};
} // namespace internal
-using MockOtp = GlobalMock<testing::StrictMock<internal::MockOtp>>;
+// Nice mock for shutdown unit tests.
+using NiceMockOtp = testing::NiceMock<internal::MockOtp>;
+// Strict mock for other unit tests.
+using MockOtp = testing::StrictMock<internal::MockOtp>;
extern "C" {
+// Note: In the functions below, we use `MockOtp` only for conciseness. The
+// static `Instance()` method returns a reference to the same
+// `internal::MockOtp` instance regardless if we use `MockOtp`, `NiceMockOtp`,
+// or `internal::MockOtp`.
+
uint32_t otp_read32(uint32_t address) {
return MockOtp::Instance().read32(address);
}
diff --git a/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_ibex.h b/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_ibex.h
index 624d8b1..0f1aa93 100644
--- a/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_ibex.h
+++ b/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_ibex.h
@@ -14,18 +14,17 @@
/**
* Mock class for sigverify_mod_exp_ibex.c
*/
-class MockSigverifyModExpIbex {
+class MockSigverifyModExpIbex : public GlobalMock<MockSigverifyModExpIbex> {
public:
MOCK_METHOD(rom_error_t, mod_exp,
(const sigverify_rsa_key_t *, const sigverify_rsa_buffer_t *,
sigverify_rsa_buffer_t *));
- virtual ~MockSigverifyModExpIbex() {}
};
} // namespace internal
using MockSigverifyModExpIbex =
- GlobalMock<testing::StrictMock<internal::MockSigverifyModExpIbex>>;
+ testing::StrictMock<internal::MockSigverifyModExpIbex>;
extern "C" {
diff --git a/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_otbn.h b/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_otbn.h
index bda1832..848a869 100644
--- a/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_otbn.h
+++ b/sw/device/silicon_creator/lib/mock_sigverify_mod_exp_otbn.h
@@ -14,18 +14,17 @@
/**
* Mock class for sigverify_mod_exp_otbn.c
*/
-class MockSigverifyModExpOtbn {
+class MockSigverifyModExpOtbn : public GlobalMock<MockSigverifyModExpOtbn> {
public:
MOCK_METHOD(rom_error_t, mod_exp,
(const sigverify_rsa_key_t *, const sigverify_rsa_buffer_t *,
sigverify_rsa_buffer_t *));
- virtual ~MockSigverifyModExpOtbn() {}
};
} // namespace internal
using MockSigverifyModExpOtbn =
- GlobalMock<testing::StrictMock<internal::MockSigverifyModExpOtbn>>;
+ testing::StrictMock<internal::MockSigverifyModExpOtbn>;
extern "C" {
diff --git a/sw/device/silicon_creator/lib/shutdown_unittest.cc b/sw/device/silicon_creator/lib/shutdown_unittest.cc
index 7a0c96c..fcdb078 100644
--- a/sw/device/silicon_creator/lib/shutdown_unittest.cc
+++ b/sw/device/silicon_creator/lib/shutdown_unittest.cc
@@ -36,28 +36,26 @@
// TODO(lowRISC/opentitan#7148): Refactor mocks into their own headers.
namespace internal {
// Create a mock for reading OTP words.
-class MockOtp {
+class MockOtp : public ::mask_rom_test::GlobalMock<MockOtp> {
public:
MOCK_METHOD(uint32_t, otp_read32, (uint32_t));
virtual ~MockOtp() {}
};
// Create a mock for shutdown functions.
-class MockShutdown {
+class MockShutdown : public ::mask_rom_test::GlobalMock<MockShutdown> {
public:
MOCK_METHOD(void, shutdown_software_escalate, ());
MOCK_METHOD(void, shutdown_keymgr_kill, ());
MOCK_METHOD(void, shutdown_flash_kill, ());
MOCK_METHOD(void, shutdown_hang, ());
- virtual ~MockShutdown() {}
};
} // namespace internal
// Use NiceMock because we aren't interested in the specifics of OTP reads,
// but we want to mock out calls to otp_read32.
-using MockOtp = mask_rom_test::GlobalMock<testing::NiceMock<internal::MockOtp>>;
-using MockShutdown =
- mask_rom_test::GlobalMock<testing::StrictMock<internal::MockShutdown>>;
+using MockOtp = testing::NiceMock<internal::MockOtp>;
+using MockShutdown = testing::StrictMock<internal::MockShutdown>;
extern "C" {
uint32_t otp_read32(uint32_t address) {
return MockOtp::Instance().otp_read32(address);
diff --git a/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h b/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h
index 0616427..5baca31 100644
--- a/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h
+++ b/sw/device/silicon_creator/mask_rom/mock_romextimage_ptrs.h
@@ -14,18 +14,15 @@
/**
* Mock class for romextimage_ptrs.h
*/
-class MockRomextimagePtrs {
+class MockRomextimagePtrs : public GlobalMock<MockRomextimagePtrs> {
public:
MOCK_METHOD(const manifest_t *, slot_a_manifest_ptr_get, ());
MOCK_METHOD(const manifest_t *, slot_b_manifest_ptr_get, ());
-
- virtual ~MockRomextimagePtrs() {}
};
} // namespace internal
-using MockRomextimagePtrs =
- GlobalMock<testing::StrictMock<internal::MockRomextimagePtrs>>;
+using MockRomextimagePtrs = testing::StrictMock<internal::MockRomextimagePtrs>;
extern "C" {