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