1 #include "pci_handler.hpp"
2
3 #include <stdplus/fd/gmock.hpp>
4 #include <stdplus/fd/managed.hpp>
5 #include <stdplus/fd/mmap.hpp>
6
7 #include <cstdint>
8 #include <memory>
9 #include <span>
10 #include <vector>
11
12 #include <gmock/gmock.h>
13 #include <gtest/gtest.h>
14
15 namespace bios_bmc_smm_error_logger
16 {
17 namespace
18 {
19
20 using ::testing::_;
21 using ::testing::ElementsAreArray;
22 using ::testing::Return;
23
24 class PciHandlerTest : public ::testing::Test
25 {
26 protected:
PciHandlerTest()27 PciHandlerTest() :
28 testMapped(
29 {std::byte(0), std::byte(11), std::byte(22), std::byte(33),
30 std::byte(44), std::byte(55), std::byte(66), std::byte(77)}),
31 fdMock(std::make_unique<stdplus::fd::FdMock>()), fdMockPtr(fdMock.get())
32 {
33 // Verify that the constructor is called as expected
34 EXPECT_CALL(*fdMockPtr, mmap(_, _, _, _))
35 .WillOnce(Return(std::span<std::byte>(testMapped)));
36 pciDataHandler = std::make_unique<PciDataHandler>(
37 testRegionAddress, testRegionSize, std::move(fdMock));
38 }
~PciHandlerTest()39 ~PciHandlerTest() override
40 {
41 // Verify that the destructor is called as expected
42 EXPECT_CALL(*fdMockPtr, munmap(_)).Times(1);
43 }
44 static constexpr uint32_t testRegionAddress = 0xF0848000;
45 // Smaller region size for easier boundary testing
46 static constexpr size_t testRegionSize = 8;
47 std::vector<std::byte> testMapped;
48 std::unique_ptr<stdplus::fd::FdMock> fdMock;
49 stdplus::fd::FdMock* fdMockPtr;
50
51 std::unique_ptr<PciDataHandler> pciDataHandler;
52 };
53
TEST_F(PciHandlerTest,GetMemoryRegionSizeSanity)54 TEST_F(PciHandlerTest, GetMemoryRegionSizeSanity)
55 {
56 EXPECT_EQ(pciDataHandler->getMemoryRegionSize(), testRegionSize);
57 }
58
TEST_F(PciHandlerTest,BoundaryChecksReadFail)59 TEST_F(PciHandlerTest, BoundaryChecksReadFail)
60 {
61 std::vector<uint8_t> emptyVector;
62 // Zero size
63 EXPECT_THAT(pciDataHandler->read(0, 0), ElementsAreArray(emptyVector));
64
65 const int offsetTooBig = testRegionSize + 1;
66 EXPECT_THAT(pciDataHandler->read(offsetTooBig, 1),
67 ElementsAreArray(emptyVector));
68 }
69
TEST_F(PciHandlerTest,BoundaryChecksWriteFail)70 TEST_F(PciHandlerTest, BoundaryChecksWriteFail)
71 {
72 std::vector<uint8_t> emptyVector;
73 // Zero size
74 EXPECT_EQ(pciDataHandler->write(0, emptyVector), 0);
75
76 const int offsetTooBig = testRegionSize + 1;
77 std::vector<uint8_t> testVector(testRegionSize - 1);
78 EXPECT_EQ(pciDataHandler->write(offsetTooBig, testVector), 0);
79 }
80
TEST_F(PciHandlerTest,ReadPasses)81 TEST_F(PciHandlerTest, ReadPasses)
82 {
83 // Normal read from 0
84 uint32_t testOffset = 0;
85 uint32_t testSize = 2;
86 std::vector<uint8_t> expectedVector{0, 11};
87 EXPECT_THAT(pciDataHandler->read(testOffset, testSize),
88 ElementsAreArray(expectedVector));
89
90 // Read to buffer boundary from non 0 offset
91 testOffset = 3;
92 testSize = testRegionSize - testOffset;
93 expectedVector.clear();
94 expectedVector = {33, 44, 55, 66, 77};
95 EXPECT_THAT(pciDataHandler->read(testOffset, testSize),
96 ElementsAreArray(expectedVector));
97
98 // Read over buffer boundary (which will read until the end)
99 testOffset = 4;
100 testSize = testRegionSize - testOffset + 1;
101 expectedVector.clear();
102 expectedVector = {44, 55, 66, 77};
103 EXPECT_THAT(pciDataHandler->read(testOffset, testSize),
104 ElementsAreArray(expectedVector));
105 }
106
TEST_F(PciHandlerTest,WritePasses)107 TEST_F(PciHandlerTest, WritePasses)
108 {
109 std::vector<std::byte> expectedMapped{
110 std::byte(0), std::byte(11), std::byte(22), std::byte(33),
111 std::byte(44), std::byte(55), std::byte(66), std::byte(77)};
112
113 // Normal write from 0
114 uint32_t testOffset = 0;
115 std::vector<uint8_t> writeVector{99, 88};
116 expectedMapped[0] = std::byte(99);
117 expectedMapped[1] = std::byte(88);
118
119 EXPECT_EQ(pciDataHandler->write(testOffset, writeVector),
120 writeVector.size());
121 EXPECT_THAT(testMapped, ElementsAreArray(expectedMapped));
122
123 // Write to buffer boundary from non 0 offset
124 testOffset = 4;
125 writeVector = {55, 44, 33, 22};
126 expectedMapped[4] = std::byte(55);
127 expectedMapped[5] = std::byte(44);
128 expectedMapped[6] = std::byte(33);
129 expectedMapped[7] = std::byte(22);
130 EXPECT_EQ(pciDataHandler->write(testOffset, writeVector),
131 writeVector.size());
132 EXPECT_THAT(testMapped, ElementsAreArray(expectedMapped));
133
134 // Read over buffer boundary (which will read until the end)
135 testOffset = 7;
136 writeVector = {12, 23, 45};
137 expectedMapped[7] = std::byte(12);
138 EXPECT_EQ(pciDataHandler->write(testOffset, writeVector),
139 testRegionSize - testOffset);
140 EXPECT_THAT(testMapped, ElementsAreArray(expectedMapped));
141 }
142
143 } // namespace
144 } // namespace bios_bmc_smm_error_logger
145