blob: e3d5621af6231ff63f7730b3daf0362a7de62a55 [file] [log] [blame]
Brandon Kimfcbc3db2022-06-06 21:26:18 -07001#include "buffer.hpp"
2#include "data_interface_mock.hpp"
3
Brandon Kim17ee1a92022-06-07 21:04:08 -07004#include <boost/endian/arithmetic.hpp>
5#include <boost/endian/conversion.hpp>
6
7#include <algorithm>
Brandon Kimfcbc3db2022-06-06 21:26:18 -07008#include <array>
9#include <cstdint>
10#include <memory>
11
12#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
15namespace bios_bmc_smm_error_logger
16{
17namespace
18{
19
20using ::testing::_;
21using ::testing::ElementsAreArray;
22using ::testing::InSequence;
23using ::testing::Return;
24
25class BufferTest : public ::testing::Test
26{
27 protected:
28 BufferTest() :
29 dataInterfaceMock(std::make_unique<DataInterfaceMock>()),
30 dataInterfaceMockPtr(dataInterfaceMock.get())
31 {
32 bufferImpl = std::make_unique<BufferImpl>(std::move(dataInterfaceMock));
33 testInitializationHeader.bmcInterfaceVersion = testBmcInterfaceVersion;
34 testInitializationHeader.queueSize = testQueueSize;
35 testInitializationHeader.ueRegionSize = testUeRegionSize;
Brandon Kim17ee1a92022-06-07 21:04:08 -070036 std::transform(testMagicNumber.begin(), testMagicNumber.end(),
37 testInitializationHeader.magicNumber.begin(),
38 [](uint32_t number) -> little_uint32_t {
39 return boost::endian::native_to_little(number);
40 });
Brandon Kimfcbc3db2022-06-06 21:26:18 -070041 }
42 ~BufferTest() override = default;
43
44 // CircularBufferHeader size is 0x30, ensure the test region is bigger
45 static constexpr size_t testRegionSize = 0x200;
46 static constexpr uint32_t testBmcInterfaceVersion = 123;
47 static constexpr uint16_t testQueueSize = 0x100;
48 static constexpr uint16_t testUeRegionSize = 0x50;
49 static constexpr std::array<uint32_t, 4> testMagicNumber = {
50 0x12345678, 0x22345678, 0x32345678, 0x42345678};
Brandon Kim17ee1a92022-06-07 21:04:08 -070051 static constexpr size_t bufferHeaderSize =
52 sizeof(struct CircularBufferHeader);
53
Brandon Kimfcbc3db2022-06-06 21:26:18 -070054 struct CircularBufferHeader testInitializationHeader
55 {};
56
57 std::unique_ptr<DataInterfaceMock> dataInterfaceMock;
58 DataInterfaceMock* dataInterfaceMockPtr;
Brandon Kimfcbc3db2022-06-06 21:26:18 -070059 std::unique_ptr<BufferImpl> bufferImpl;
60};
61
62TEST_F(BufferTest, BufferInitializeEraseFail)
63{
64 InSequence s;
65
66 EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
67 .WillOnce(Return(testRegionSize));
68 const std::vector<uint8_t> emptyArray(testRegionSize, 0);
69 // Return a smaller write than the intended testRegionSize to test the error
70 EXPECT_CALL(*dataInterfaceMockPtr, write(0, ElementsAreArray(emptyArray)))
71 .WillOnce(Return(testRegionSize - 1));
72 EXPECT_THROW(
73 try {
74 bufferImpl->initialize(testBmcInterfaceVersion, testQueueSize,
75 testUeRegionSize, testMagicNumber);
76 } catch (const std::runtime_error& e) {
77 EXPECT_STREQ(e.what(), "Buffer initialization only erased '511'");
78 throw;
79 },
80 std::runtime_error);
81
82 EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
83 .WillOnce(Return(testRegionSize));
84 EXPECT_CALL(*dataInterfaceMockPtr, write(0, ElementsAreArray(emptyArray)))
85 .WillOnce(Return(testRegionSize));
86 // Return a smaller write than the intended initializationHeader to test the
87 // error
88 EXPECT_CALL(*dataInterfaceMockPtr, write(0, _)).WillOnce(Return(0));
89 EXPECT_THROW(
90 try {
91 bufferImpl->initialize(testBmcInterfaceVersion, testQueueSize,
92 testUeRegionSize, testMagicNumber);
93 } catch (const std::runtime_error& e) {
94 EXPECT_STREQ(
95 e.what(),
96 "Buffer initialization buffer header write only wrote '0'");
97 throw;
98 },
99 std::runtime_error);
100}
101
102TEST_F(BufferTest, BufferInitializePass)
103{
104 InSequence s;
105 EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
106 .WillOnce(Return(testRegionSize));
107 const std::vector<uint8_t> emptyArray(testRegionSize, 0);
108 EXPECT_CALL(*dataInterfaceMockPtr, write(0, ElementsAreArray(emptyArray)))
109 .WillOnce(Return(testRegionSize));
110
111 uint8_t* testInitializationHeaderPtr =
112 reinterpret_cast<uint8_t*>(&testInitializationHeader);
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700113 EXPECT_CALL(*dataInterfaceMockPtr,
114 write(0, ElementsAreArray(testInitializationHeaderPtr,
Brandon Kim17ee1a92022-06-07 21:04:08 -0700115 bufferHeaderSize)))
116 .WillOnce(Return(bufferHeaderSize));
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700117 EXPECT_NO_THROW(bufferImpl->initialize(testBmcInterfaceVersion,
118 testQueueSize, testUeRegionSize,
119 testMagicNumber));
120}
121
Brandon Kim17ee1a92022-06-07 21:04:08 -0700122TEST_F(BufferTest, BufferHeaderReadFail)
123{
124 std::vector<std::uint8_t> testBytesRead{};
125 EXPECT_CALL(*dataInterfaceMockPtr, read(0, bufferHeaderSize))
126 .WillOnce(Return(testBytesRead));
127 EXPECT_THROW(
128 try {
129 bufferImpl->readBufferHeader();
130 } catch (const std::runtime_error& e) {
131 EXPECT_STREQ(e.what(),
132 "Buffer header read only read '0', expected '48'");
133 throw;
134 },
135 std::runtime_error);
136}
137
138TEST_F(BufferTest, BufferHeaderReadPass)
139{
140 uint8_t* testInitializationHeaderPtr =
141 reinterpret_cast<uint8_t*>(&testInitializationHeader);
142 std::vector<uint8_t> testInitializationHeaderVector(
143 testInitializationHeaderPtr,
144 testInitializationHeaderPtr + bufferHeaderSize);
145
146 EXPECT_CALL(*dataInterfaceMockPtr, read(0, bufferHeaderSize))
147 .WillOnce(Return(testInitializationHeaderVector));
148 EXPECT_NO_THROW(bufferImpl->readBufferHeader());
149 EXPECT_EQ(bufferImpl->getCachedBufferHeader(), testInitializationHeader);
150}
151
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700152} // namespace
153} // namespace bios_bmc_smm_error_logger