1 #include "buffer.hpp"
2 #include "data_interface_mock.hpp"
3 
4 #include <array>
5 #include <cstdint>
6 #include <memory>
7 
8 #include <gmock/gmock.h>
9 #include <gtest/gtest.h>
10 
11 namespace bios_bmc_smm_error_logger
12 {
13 namespace
14 {
15 
16 using ::testing::_;
17 using ::testing::ElementsAreArray;
18 using ::testing::InSequence;
19 using ::testing::Return;
20 
21 class BufferTest : public ::testing::Test
22 {
23   protected:
24     BufferTest() :
25         dataInterfaceMock(std::make_unique<DataInterfaceMock>()),
26         dataInterfaceMockPtr(dataInterfaceMock.get())
27     {
28         bufferImpl = std::make_unique<BufferImpl>(std::move(dataInterfaceMock));
29         testInitializationHeader.bmcInterfaceVersion = testBmcInterfaceVersion;
30         testInitializationHeader.queueSize = testQueueSize;
31         testInitializationHeader.ueRegionSize = testUeRegionSize;
32         testInitializationHeader.magicNumber = testMagicNumber;
33     }
34     ~BufferTest() override = default;
35 
36     // CircularBufferHeader size is 0x30, ensure the test region is bigger
37     static constexpr size_t testRegionSize = 0x200;
38     static constexpr uint32_t testBmcInterfaceVersion = 123;
39     static constexpr uint16_t testQueueSize = 0x100;
40     static constexpr uint16_t testUeRegionSize = 0x50;
41     static constexpr std::array<uint32_t, 4> testMagicNumber = {
42         0x12345678, 0x22345678, 0x32345678, 0x42345678};
43     struct CircularBufferHeader testInitializationHeader
44     {};
45 
46     std::unique_ptr<DataInterfaceMock> dataInterfaceMock;
47     DataInterfaceMock* dataInterfaceMockPtr;
48 
49     std::unique_ptr<BufferImpl> bufferImpl;
50 };
51 
52 TEST_F(BufferTest, BufferInitializeEraseFail)
53 {
54     InSequence s;
55 
56     EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
57         .WillOnce(Return(testRegionSize));
58     const std::vector<uint8_t> emptyArray(testRegionSize, 0);
59     // Return a smaller write than the intended testRegionSize to test the error
60     EXPECT_CALL(*dataInterfaceMockPtr, write(0, ElementsAreArray(emptyArray)))
61         .WillOnce(Return(testRegionSize - 1));
62     EXPECT_THROW(
63         try {
64             bufferImpl->initialize(testBmcInterfaceVersion, testQueueSize,
65                                    testUeRegionSize, testMagicNumber);
66         } catch (const std::runtime_error& e) {
67             EXPECT_STREQ(e.what(), "Buffer initialization only erased '511'");
68             throw;
69         },
70         std::runtime_error);
71 
72     EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
73         .WillOnce(Return(testRegionSize));
74     EXPECT_CALL(*dataInterfaceMockPtr, write(0, ElementsAreArray(emptyArray)))
75         .WillOnce(Return(testRegionSize));
76     // Return a smaller write than the intended initializationHeader to test the
77     // error
78     EXPECT_CALL(*dataInterfaceMockPtr, write(0, _)).WillOnce(Return(0));
79     EXPECT_THROW(
80         try {
81             bufferImpl->initialize(testBmcInterfaceVersion, testQueueSize,
82                                    testUeRegionSize, testMagicNumber);
83         } catch (const std::runtime_error& e) {
84             EXPECT_STREQ(
85                 e.what(),
86                 "Buffer initialization buffer header write only wrote '0'");
87             throw;
88         },
89         std::runtime_error);
90 }
91 
92 TEST_F(BufferTest, BufferInitializePass)
93 {
94     InSequence s;
95     EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
96         .WillOnce(Return(testRegionSize));
97     const std::vector<uint8_t> emptyArray(testRegionSize, 0);
98     EXPECT_CALL(*dataInterfaceMockPtr, write(0, ElementsAreArray(emptyArray)))
99         .WillOnce(Return(testRegionSize));
100 
101     uint8_t* testInitializationHeaderPtr =
102         reinterpret_cast<uint8_t*>(&testInitializationHeader);
103     size_t initializationHeaderSize = sizeof(testInitializationHeader);
104     EXPECT_CALL(*dataInterfaceMockPtr,
105                 write(0, ElementsAreArray(testInitializationHeaderPtr,
106                                           initializationHeaderSize)))
107         .WillOnce(Return(initializationHeaderSize));
108     EXPECT_NO_THROW(bufferImpl->initialize(testBmcInterfaceVersion,
109                                            testQueueSize, testUeRegionSize,
110                                            testMagicNumber));
111 }
112 
113 } // namespace
114 } // namespace bios_bmc_smm_error_logger
115