Software APIs
sw
device
lib
base
global_mock.h
1
// Copyright lowRISC contributors (OpenTitan project).
2
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3
// SPDX-License-Identifier: Apache-2.0
4
5
#ifndef OPENTITAN_SW_DEVICE_LIB_BASE_GLOBAL_MOCK_H_
6
#define OPENTITAN_SW_DEVICE_LIB_BASE_GLOBAL_MOCK_H_
7
8
#include <sstream>
9
#include <typeinfo>
10
#include <utility>
11
12
#include "gmock/gmock.h"
13
#include "gtest/gtest.h"
14
15
namespace
global_mock {
16
17
/**
18
* Base class for mocks used in unit tests.
19
*
20
* If a class `Mock` derives from `GlobalMock<Mock>`, `GlobalMock<Mock>`
21
* ensures that there is at most one instance of `Mock` at a time (checked at
22
* runtime) and makes this instance globally accessible via the static `Mock
23
* &Instance()` method.
24
*
25
* Mock classes should be globally accessible so that mock functions can call
26
* their methods during tests. They can also be strict or nice depending on
27
* tests' needs. Mock classes that satisfy both requirements can be defined as
28
* follows:
29
*
30
* namespace global_mock {
31
* namespace internal {
32
* class MockFoo : public GlobalMock<MockFoo> {
33
* ...
34
* };
35
* } // namespace internal
36
* // Type alias for making `internal::MockFoo` a strict mock.
37
* using MockFoo = testing::StrictMock<internal::MockFoo>;
38
* // Type alias for making `internal::MockFoo` a nice mock if needed.
39
* using NiceMockFoo = testing::NiceMock<internal::MockFoo>;
40
* ...
41
* } // namespace rom_test
42
*
43
* This construction also ensures that we cannot have `MockFoo` and
44
* `NiceMockFoo` instantiated at the same time since they both derive from the
45
* same class, i.e. `GlobalMock<internal::MockFoo>`.
46
*/
47
template
<
typename
Mock>
48
class
GlobalMock
{
49
public
:
50
GlobalMock
() {
51
if
(instance_ !=
nullptr
) {
52
std::stringstream ss;
53
ss <<
"Mock `"
<<
typeid
(
GlobalMock
).name()
54
<<
"` is already instantiated."
;
55
throw
std::runtime_error(std::move(ss).str());
56
}
57
instance_ =
this
;
58
}
59
60
// Note: Destructors of mock classes must be virtual for `testing::StrictMock`
61
// and `testing::NiceMock` to work correctly.
62
virtual
~
GlobalMock
() { instance_ =
nullptr
; }
63
64
static
Mock &Instance() {
65
if
(instance_ ==
nullptr
) {
66
std::stringstream ss;
67
ss <<
"Mock `"
<<
typeid
(
GlobalMock
).name() <<
"` not instantiated yet."
;
68
throw
std::runtime_error(std::move(ss).str());
69
}
70
return
*
static_cast<
Mock *
>
(instance_);
71
}
72
73
GlobalMock
(
const
GlobalMock
&) =
delete
;
74
GlobalMock
&operator=(
const
GlobalMock
&) =
delete
;
75
GlobalMock
(
GlobalMock
&&) =
delete
;
76
GlobalMock
&operator=(
GlobalMock
&&) =
delete
;
77
78
private
:
79
static
GlobalMock<Mock>
*instance_;
80
};
81
template
<
typename
Mock>
82
GlobalMock<Mock>
*
GlobalMock<Mock>::instance_
=
nullptr
;
83
84
}
// namespace global_mock
85
#endif
// OPENTITAN_SW_DEVICE_LIB_BASE_GLOBAL_MOCK_H_
Return to
OpenTitan Documentation