1 #include "fru_utils.hpp" 2 3 #include <algorithm> 4 #include <array> 5 #include <iterator> 6 7 #include "gtest/gtest.h" 8 9 extern "C" 10 { 11 // Include for I2C_SMBUS_BLOCK_MAX 12 #include <linux/i2c.h> 13 } 14 15 TEST(ValidateHeaderTest, InvalidFruVersionReturnsFalse) 16 { 17 // Validates the FruVersion is checked for the only legal value. 18 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = { 19 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 20 21 EXPECT_FALSE(validateHeader(fruHeader)); 22 } 23 24 TEST(ValidateHeaderTest, InvalidReservedReturnsFalse) 25 { 26 // Validates the reserved bit(7:4) of first bytes. 27 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = { 28 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 29 30 EXPECT_FALSE(validateHeader(fruHeader)); 31 } 32 33 TEST(ValidateHeaderTest, InvalidPaddingReturnsFalse) 34 { 35 // Validates the padding byte (7th byte). 36 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = { 37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; 38 39 EXPECT_FALSE(validateHeader(fruHeader)); 40 } 41 42 TEST(ValidateHeaderTest, InvalidChecksumReturnsFalse) 43 { 44 // Validates the checksum, check for incorrect value. 45 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = { 46 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00}; 47 48 EXPECT_FALSE(validateHeader(fruHeader)); 49 } 50 51 TEST(ValidateHeaderTest, ValidChecksumReturnsTrue) 52 { 53 // Validates the checksum, check for correct value. 54 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = { 55 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5}; 56 57 EXPECT_TRUE(validateHeader(fruHeader)); 58 } 59 60 TEST(VerifyOffsetTest, EmptyFruDataReturnsFalse) 61 { 62 // Validates the FruData size is checked for non empty. 63 std::vector<uint8_t> fruData = {}; 64 65 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 0)); 66 } 67 68 TEST(VerifyOffsetTest, AreaOutOfRangeReturnsFalse) 69 { 70 // Validates the FruArea value, check if it is within range. 71 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00}; 73 74 unsigned int areaOutOfRange = 8; 75 EXPECT_FALSE( 76 verifyOffset(fruData, static_cast<fruAreas>(areaOutOfRange), 0)); 77 } 78 79 TEST(VerifyOffsetTest, OverlapNextAreaReturnsFalse) 80 { 81 // Validates the Overlap of offsets with overlapped values. 82 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03, 83 0x04, 0x00, 0x00, 0x00}; 84 85 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 2)); 86 } 87 88 TEST(VerifyOffsetTest, OverlapPrevAreaReturnsFalse) 89 { 90 // Validates the Overlap of offsets with overlapped values. 91 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x03, 0x02, 92 0x07, 0x00, 0x00, 0x00}; 93 94 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaProduct, 2)); 95 } 96 97 TEST(VerifyOffsetTest, ValidInputDataNoOverlapReturnsTrue) 98 { 99 // Validates all inputs with expected value and no overlap. 100 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03, 101 0x04, 0x00, 0x00, 0x00}; 102 103 EXPECT_TRUE(verifyOffset(fruData, fruAreas::fruAreaChassis, 1)); 104 } 105 106 TEST(VerifyChecksumTest, EmptyInput) 107 { 108 std::vector<uint8_t> data = {}; 109 110 EXPECT_EQ(calculateChecksum(data), 0); 111 } 112 113 TEST(VerifyChecksumTest, SingleOneInput) 114 { 115 std::vector<uint8_t> data(1, 1); 116 117 EXPECT_EQ(calculateChecksum(data), 255); 118 } 119 120 TEST(VerifyChecksumTest, AllOneInput) 121 { 122 std::vector<uint8_t> data(256, 1); 123 124 EXPECT_EQ(calculateChecksum(data), 0); 125 } 126 127 TEST(VerifyChecksumTest, WrapBoundaryLow) 128 { 129 std::vector<uint8_t> data = {255, 0}; 130 131 EXPECT_EQ(calculateChecksum(data), 1); 132 } 133 134 TEST(VerifyChecksumTest, WrapBoundaryExact) 135 { 136 std::vector<uint8_t> data = {255, 1}; 137 138 EXPECT_EQ(calculateChecksum(data), 0); 139 } 140 141 TEST(VerifyChecksumTest, WrapBoundaryHigh) 142 { 143 std::vector<uint8_t> data = {255, 2}; 144 145 EXPECT_EQ(calculateChecksum(data), 255); 146 } 147 148 int64_t getDataTempl(const std::vector<uint8_t>& data, 149 [[maybe_unused]] int flag, [[maybe_unused]] int file, 150 [[maybe_unused]] uint16_t address, off_t offset, 151 size_t length, uint8_t* outBuf) 152 { 153 if (offset >= static_cast<off_t>(data.size())) 154 { 155 return 0; 156 } 157 158 uint16_t idx; 159 for (idx = offset; idx < data.size() && idx < offset + length; 160 ++idx, ++outBuf) 161 { 162 *outBuf = data[idx]; 163 } 164 165 return idx - offset; 166 } 167 168 TEST(FindFRUHeaderTest, InvalidHeader) 169 { 170 const std::vector<uint8_t> data = {255, 16}; 171 off_t offset = 0; 172 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; 173 auto getData = [&data](auto fl, auto fi, auto a, auto o, auto l, auto* b) { 174 return getDataTempl(data, fl, fi, a, o, l, b); 175 }; 176 177 EXPECT_FALSE(findFRUHeader(0, 0, 0, getData, "error", blockData, offset)); 178 } 179 180 TEST(FindFRUHeaderTest, NoData) 181 { 182 const std::vector<uint8_t> data = {}; 183 off_t offset = 0; 184 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; 185 auto getData = [&data](auto fl, auto fi, auto a, auto o, auto l, auto* b) { 186 return getDataTempl(data, fl, fi, a, o, l, b); 187 }; 188 189 EXPECT_FALSE(findFRUHeader(0, 0, 0, getData, "error", blockData, offset)); 190 } 191 192 TEST(FindFRUHeaderTest, ValidHeader) 193 { 194 const std::vector<uint8_t> data = {0x01, 0x00, 0x01, 0x02, 195 0x03, 0x04, 0x00, 0xf5}; 196 off_t offset = 0; 197 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; 198 auto getData = [&data](auto fl, auto fi, auto a, auto o, auto l, auto* b) { 199 return getDataTempl(data, fl, fi, a, o, l, b); 200 }; 201 202 EXPECT_TRUE(findFRUHeader(0, 0, 0, getData, "error", blockData, offset)); 203 EXPECT_EQ(0, offset); 204 } 205 206 TEST(FindFRUHeaderTest, TyanInvalidHeader) 207 { 208 std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0}; 209 data.resize(0x6000 + I2C_SMBUS_BLOCK_MAX); 210 off_t offset = 0; 211 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; 212 auto getData = [&data](auto fl, auto fi, auto a, auto o, auto l, auto* b) { 213 return getDataTempl(data, fl, fi, a, o, l, b); 214 }; 215 216 EXPECT_FALSE(findFRUHeader(0, 0, 0, getData, "error", blockData, offset)); 217 } 218 219 TEST(FindFRUHeaderTest, TyanNoData) 220 { 221 const std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0}; 222 off_t offset = 0; 223 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; 224 auto getData = [&data](auto fl, auto fi, auto a, auto o, auto l, auto* b) { 225 return getDataTempl(data, fl, fi, a, o, l, b); 226 }; 227 228 EXPECT_FALSE(findFRUHeader(0, 0, 0, getData, "error", blockData, offset)); 229 } 230 231 TEST(FindFRUHeaderTest, TyanValidHeader) 232 { 233 std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0}; 234 data.resize(0x6000); 235 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = { 236 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5}; 237 copy(fruHeader.begin(), fruHeader.end(), back_inserter(data)); 238 239 off_t offset = 0; 240 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; 241 auto getData = [&data](auto fl, auto fi, auto a, auto o, auto l, auto* b) { 242 return getDataTempl(data, fl, fi, a, o, l, b); 243 }; 244 245 EXPECT_TRUE(findFRUHeader(0, 0, 0, getData, "error", blockData, offset)); 246 EXPECT_EQ(0x6000, offset); 247 } 248