| // Copied from |
| // https://github.com/openbmc/entity-manager/blob/master/test/test_fru-utils.cpp. |
| |
| #include "fru_utils.hpp" |
| |
| #include <algorithm> |
| #include <array> |
| #include <cstring> |
| #include <iterator> |
| |
| #include "gtest/gtest.h" |
| |
| TEST(ValidateHeaderTest, InvalidFruVersionReturnsFalse) |
| { |
| // Validates the FruVersion is checked for the only legal value. |
| constexpr std::array<uint8_t, SMBUS_BLOCK_MAX> fruHeader = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| EXPECT_FALSE(validateHeader(fruHeader)); |
| } |
| |
| TEST(ValidateHeaderTest, InvalidReservedReturnsFalse) |
| { |
| // Validates the reserved bit(7:4) of first bytes. |
| constexpr std::array<uint8_t, SMBUS_BLOCK_MAX> fruHeader = { |
| 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| EXPECT_FALSE(validateHeader(fruHeader)); |
| } |
| |
| TEST(ValidateHeaderTest, InvalidPaddingReturnsFalse) |
| { |
| // Validates the padding byte (7th byte). |
| constexpr std::array<uint8_t, SMBUS_BLOCK_MAX> fruHeader = { |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; |
| |
| EXPECT_FALSE(validateHeader(fruHeader)); |
| } |
| |
| TEST(ValidateHeaderTest, InvalidChecksumReturnsFalse) |
| { |
| // Validates the checksum, check for incorrect value. |
| constexpr std::array<uint8_t, SMBUS_BLOCK_MAX> fruHeader = { |
| 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00}; |
| |
| EXPECT_FALSE(validateHeader(fruHeader)); |
| } |
| |
| TEST(ValidateHeaderTest, ValidChecksumReturnsTrue) |
| { |
| // Validates the checksum, check for correct value. |
| constexpr std::array<uint8_t, SMBUS_BLOCK_MAX> fruHeader = { |
| 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5}; |
| |
| EXPECT_TRUE(validateHeader(fruHeader)); |
| } |
| |
| TEST(VerifyOffsetTest, EmptyFruDataReturnsFalse) |
| { |
| // Validates the FruData size is checked for non empty. |
| std::vector<uint8_t> fruData = {}; |
| |
| EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 0)); |
| } |
| |
| TEST(VerifyOffsetTest, AreaOutOfRangeReturnsFalse) |
| { |
| // Validates the FruArea value, check if it is within range. |
| const std::vector<uint8_t> fruData = {0x01, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| |
| unsigned int areaOutOfRange = 8; |
| EXPECT_FALSE( |
| verifyOffset(fruData, static_cast<fruAreas>(areaOutOfRange), 0)); |
| } |
| |
| TEST(VerifyOffsetTest, OverlapNextAreaReturnsFalse) |
| { |
| // Validates the Overlap of offsets with overlapped values. |
| const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03, |
| 0x04, 0x00, 0x00, 0x00}; |
| |
| EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 2)); |
| } |
| |
| TEST(VerifyOffsetTest, OverlapPrevAreaReturnsFalse) |
| { |
| // Validates the Overlap of offsets with overlapped values. |
| const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x03, 0x02, |
| 0x07, 0x00, 0x00, 0x00}; |
| |
| EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaProduct, 2)); |
| } |
| |
| TEST(VerifyOffsetTest, ValidInputDataNoOverlapReturnsTrue) |
| { |
| // Validates all inputs with expected value and no overlap. |
| const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03, |
| 0x04, 0x00, 0x00, 0x00}; |
| |
| EXPECT_TRUE(verifyOffset(fruData, fruAreas::fruAreaChassis, 1)); |
| } |
| |
| TEST(VerifyChecksumTest, EmptyInput) |
| { |
| std::vector<uint8_t> data = {}; |
| |
| EXPECT_EQ(calculateChecksum(data), 0); |
| } |
| |
| TEST(VerifyChecksumTest, SingleOneInput) |
| { |
| std::vector<uint8_t> data(1, 1); |
| |
| EXPECT_EQ(calculateChecksum(data), 255); |
| } |
| |
| TEST(VerifyChecksumTest, AllOneInput) |
| { |
| std::vector<uint8_t> data(256, 1); |
| |
| EXPECT_EQ(calculateChecksum(data), 0); |
| } |
| |
| TEST(VerifyChecksumTest, WrapBoundaryLow) |
| { |
| std::vector<uint8_t> data = {255, 0}; |
| |
| EXPECT_EQ(calculateChecksum(data), 1); |
| } |
| |
| TEST(VerifyChecksumTest, WrapBoundaryExact) |
| { |
| std::vector<uint8_t> data = {255, 1}; |
| |
| EXPECT_EQ(calculateChecksum(data), 0); |
| } |
| |
| TEST(VerifyChecksumTest, WrapBoundaryHigh) |
| { |
| std::vector<uint8_t> data = {255, 2}; |
| |
| EXPECT_EQ(calculateChecksum(data), 255); |
| } |
| |
| int64_t getDataTempl(const std::vector<uint8_t>& data, off_t offset, |
| size_t length, uint8_t* outBuf) |
| { |
| if (offset >= static_cast<off_t>(data.size())) |
| { |
| return 0; |
| } |
| |
| uint16_t idx = offset; |
| // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) |
| for (; idx < std::min(static_cast<uint32_t>(data.size()), |
| static_cast<uint32_t>(offset + length)); |
| ++idx, ++outBuf) |
| { |
| *outBuf = data[idx]; |
| } |
| |
| return idx - offset; |
| } |
| |
| TEST(FindFRUHeaderTest, InvalidHeader) |
| { |
| const std::vector<uint8_t> data = {255, 16}; |
| off_t offset = 0; |
| std::array<uint8_t, SMBUS_BLOCK_MAX> blockData{}; |
| auto getData = [&data](auto o, auto l, auto* b) { |
| return getDataTempl(data, o, l, b); |
| }; |
| FRUReader reader(getData); |
| |
| EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset)); |
| } |
| |
| TEST(FindFRUHeaderTest, NoData) |
| { |
| const std::vector<uint8_t> data = {}; |
| off_t offset = 0; |
| std::array<uint8_t, SMBUS_BLOCK_MAX> blockData{}; |
| auto getData = [&data](auto o, auto l, auto* b) { |
| return getDataTempl(data, o, l, b); |
| }; |
| FRUReader reader(getData); |
| |
| EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset)); |
| } |
| |
| TEST(FindFRUHeaderTest, ValidHeader) |
| { |
| const std::vector<uint8_t> data = {0x01, 0x00, 0x01, 0x02, |
| 0x03, 0x04, 0x00, 0xf5}; |
| off_t offset = 0; |
| std::array<uint8_t, SMBUS_BLOCK_MAX> blockData{}; |
| auto getData = [&data](auto o, auto l, auto* b) { |
| return getDataTempl(data, o, l, b); |
| }; |
| FRUReader reader(getData); |
| |
| EXPECT_TRUE(findFRUHeader(reader, "error", blockData, offset)); |
| EXPECT_EQ(0, offset); |
| } |
| |
| TEST(FindFRUHeaderTest, TyanInvalidHeader) |
| { |
| std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0}; |
| data.resize(0x6000 + SMBUS_BLOCK_MAX); |
| off_t offset = 0; |
| std::array<uint8_t, SMBUS_BLOCK_MAX> blockData{}; |
| auto getData = [&data](auto o, auto l, auto* b) { |
| return getDataTempl(data, o, l, b); |
| }; |
| FRUReader reader(getData); |
| |
| EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset)); |
| } |
| |
| TEST(FindFRUHeaderTest, TyanNoData) |
| { |
| const std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0}; |
| off_t offset = 0; |
| std::array<uint8_t, SMBUS_BLOCK_MAX> blockData{}; |
| auto getData = [&data](auto o, auto l, auto* b) { |
| return getDataTempl(data, o, l, b); |
| }; |
| FRUReader reader(getData); |
| |
| EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset)); |
| } |
| |
| TEST(FindFRUHeaderTest, TyanValidHeader) |
| { |
| std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0}; |
| data.resize(0x6000); |
| constexpr std::array<uint8_t, SMBUS_BLOCK_MAX> fruHeader = { |
| 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5}; |
| copy(fruHeader.begin(), fruHeader.end(), back_inserter(data)); |
| |
| off_t offset = 0; |
| std::array<uint8_t, SMBUS_BLOCK_MAX> blockData{}; |
| auto getData = [&data](auto o, auto l, auto* b) { |
| return getDataTempl(data, o, l, b); |
| }; |
| FRUReader reader(getData); |
| |
| EXPECT_TRUE(findFRUHeader(reader, "error", blockData, offset)); |
| EXPECT_EQ(0x6000, offset); |
| } |
| |
| TEST(FormatIPMIFRUTest, EmptyFruReturnsError) |
| { |
| std::vector<uint8_t> fruBytes = {}; |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resErr); |
| } |
| |
| TEST(FormatIPMIFRUTest, YCCapCaseSetsCxlDevice) |
| { |
| std::vector<uint8_t> fruBytes = { |
| // Common Header (8 bytes) |
| 0x01, // Version |
| 0x00, // Internal offset |
| 0x00, // Chassis offset |
| 0x00, // Board offset |
| 0x01, // Product offset (*8 = 8) |
| 0x00, // Multirecord offset |
| 0x00, // Pad |
| 0xfe, // Header checksum |
| |
| // Product Area (starts at 8) |
| 0x01, // Format version |
| 0x05, // Area length (*8 = 40 bytes) |
| 0x19, // Language code (english) |
| ((3 << 6) | 3), 'F', 'O', 'O', // Manufacturer: "FOO" |
| ((3 << 6) | 7), 'Y', '-', 'C', 'A', 'B', 'L', |
| 'E', // Product Name: "Y-CABLE" |
| ((3 << 6) | 3), '1', '2', '3', // Part Number |
| ((3 << 6) | 3), '4', '5', '6', // Version |
| ((3 << 6) | 3), '7', '8', '9', // Serial Number |
| ((3 << 6) | 3), 'A', 'B', 'C', // Asset Tag |
| ((3 << 6) | 3), 'D', 'E', 'F', // FRU Version ID |
| 0xc1, // end of fields |
| 0, 0, 0, // padding |
| 0 // checksum placeholder |
| }; |
| fruBytes.resize(48); |
| fruBytes[47] = |
| calculateChecksum(fruBytes.begin() + 8, fruBytes.begin() + 47); |
| |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["PRODUCT_PRODUCT_NAME"], "Y-CABLE"); |
| EXPECT_EQ(result["cxl_device"], "true"); |
| } |
| |
| TEST(FormatIPMIFRUTest, YCSmallCaseSetsCxlDevice) |
| { |
| std::vector<uint8_t> fruBytes = { |
| // Common Header (8 bytes) |
| 0x01, // Version |
| 0x00, // Internal offset |
| 0x00, // Chassis offset |
| 0x00, // Board offset |
| 0x01, // Product offset (*8 = 8) |
| 0x00, // Multirecord offset |
| 0x00, // Pad |
| 0xfe, // Header checksum |
| |
| // Product Area (starts at 8) |
| 0x01, // Format version |
| 0x05, // Area length (*8 = 40 bytes) |
| 0x19, // Language code (english) |
| ((3 << 6) | 3), 'F', 'O', 'O', // Manufacturer: "FOO" |
| ((3 << 6) | 7), 'y', '-', 'c', 'a', 'b', 'l', |
| 'e', // Product Name: "y-cable" |
| ((3 << 6) | 3), '1', '2', '3', // Part Number |
| ((3 << 6) | 3), '4', '5', '6', // Version |
| ((3 << 6) | 3), '7', '8', '9', // Serial Number |
| ((3 << 6) | 3), 'A', 'B', 'C', // Asset Tag |
| ((3 << 6) | 3), 'D', 'E', 'F', // FRU Version ID |
| 0xc1, // end of fields |
| 0, 0, 0, // padding |
| 0 // checksum placeholder |
| }; |
| fruBytes.resize(48); |
| fruBytes[47] = |
| calculateChecksum(fruBytes.begin() + 8, fruBytes.begin() + 47); |
| |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["PRODUCT_PRODUCT_NAME"], "y-cable"); |
| EXPECT_EQ(result["cxl_device"], "true"); |
| } |
| |
| TEST(FormatIPMIFRUTest, YCCamelCaseSetsCxlDevice) |
| { |
| std::vector<uint8_t> fruBytes = { |
| // Common Header (8 bytes) |
| 0x01, // Version |
| 0x00, // Internal offset |
| 0x00, // Chassis offset |
| 0x00, // Board offset |
| 0x01, // Product offset (*8 = 8) |
| 0x00, // Multirecord offset |
| 0x00, // Pad |
| 0xfe, // Header checksum |
| |
| // Product Area (starts at 8) |
| 0x01, // Format version |
| 0x05, // Area length (*8 = 40 bytes) |
| 0x19, // Language code (english) |
| ((3 << 6) | 3), 'F', 'O', 'O', // Manufacturer: "FOO" |
| ((3 << 6) | 7), 'Y', '-', 'C', 'a', 'b', 'l', |
| 'e', // Product Name: "Y-Cable" |
| ((3 << 6) | 3), '1', '2', '3', // Part Number |
| ((3 << 6) | 3), '4', '5', '6', // Version |
| ((3 << 6) | 3), '7', '8', '9', // Serial Number |
| ((3 << 6) | 3), 'A', 'B', 'C', // Asset Tag |
| ((3 << 6) | 3), 'D', 'E', 'F', // FRU Version ID |
| 0xc1, // end of fields |
| 0, 0, 0, // padding |
| 0 // checksum placeholder |
| }; |
| fruBytes.resize(48); |
| fruBytes[47] = |
| calculateChecksum(fruBytes.begin() + 8, fruBytes.begin() + 47); |
| |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["PRODUCT_PRODUCT_NAME"], "Y-Cable"); |
| EXPECT_EQ(result["cxl_device"], "true"); |
| } |
| |
| TEST(FormatIPMIFRUTest, NormalProductNameDoesNotSetCxlDevice) |
| { |
| std::vector<uint8_t> fruBytes = { |
| // Common Header (8 bytes) |
| 0x01, // Version |
| 0x00, // Internal offset |
| 0x00, // Chassis offset |
| 0x00, // Board offset |
| 0x01, // Product offset (*8 = 8) |
| 0x00, // Multirecord offset |
| 0x00, // Pad |
| 0xfe, // Header checksum |
| |
| // Product Area (starts at 8) |
| 0x01, // Format version |
| 0x05, // Area length (*8 = 40 bytes) |
| 0x19, // Language code (english) |
| ((3 << 6) | 3), 'F', 'O', 'O', // Manufacturer: "FOO" |
| ((3 << 6) | 8), 'N', 'o', 'r', 'm', 'a', 'l', 'P', |
| 'D', // Product Name: "NormalPD" |
| ((3 << 6) | 3), '1', '2', '3', // Part Number |
| ((3 << 6) | 3), '4', '5', '6', // Version |
| ((3 << 6) | 3), '7', '8', '9', // Serial Number |
| ((3 << 6) | 3), 'A', 'B', 'C', // Asset Tag |
| ((3 << 6) | 3), 'D', 'E', 'F', // FRU Version ID |
| 0xc1, // end of fields |
| 0, 0, // padding |
| 0 // checksum placeholder |
| }; |
| fruBytes.resize(48); |
| fruBytes[47] = |
| calculateChecksum(fruBytes.begin() + 8, fruBytes.begin() + 47); |
| |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["PRODUCT_PRODUCT_NAME"], "NormalPD"); |
| EXPECT_EQ(result["cxl_device"], "false"); |
| } |
| |
| TEST(FormatIPMIFRUTest, YCableP0P1SetCxlDevice) |
| { |
| const std::string_view product_names_under_test[] = {"P0", "P1"}; |
| std::vector<uint8_t> fruBytes = { |
| // Common Header (8 bytes) |
| 0x01, // Version |
| 0x00, // Internal offset |
| 0x00, // Chassis offset |
| 0x01, // Board offset |
| 0x00, // Product offset (*8 = 8) |
| 0x00, // Multirecord offset |
| 0x00, // Pad |
| 0xfe, // Header checksum |
| |
| // Board Area (starts at 8) |
| 0x01, // Format version |
| 0x04, // Area length (*8 = 32 bytes) |
| 0x19, // Language code (english) |
| 0x00, 0x00, 0x00, // MFG Date/Time |
| ((3 << 6) | 3), 'F', 'O', 'O', // Manufacturer: "FOO" |
| ((3 << 6) | 2), 'P', '0', // Product Name: "P0"/"P1" |
| ((3 << 6) | 3), '7', '8', '9', // Serial Number |
| ((3 << 6) | 3), '1', '2', '3', // Part Number |
| ((3 << 6) | 3), 'D', 'E', 'F', // FRU Version ID |
| 0xc1, // end of fields |
| 0, 0, 0, 0, 0, // padding |
| 0 // checksum placeholder |
| }; |
| fruBytes.resize(40); |
| for (const auto& product_name : product_names_under_test) |
| { |
| fruBytes[20] = product_name[1]; |
| fruBytes[39] = |
| calculateChecksum(fruBytes.begin() + 8, fruBytes.begin() + 39); |
| |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["BOARD_PRODUCT_NAME"], product_name); |
| EXPECT_EQ(result["cxl_device"], "true"); |
| } |
| } |
| |
| TEST(FormatIPMIFRUTest, YCableDcmioMxioSetCxlDevice) |
| { |
| const std::string_view product_names_under_test[] = { |
| "x16_GenZ_to_2x8_mxio_P0\0", "x16_GenZ_to_2x8_mxio_P1\0", |
| "x16_GenZ_to_2x8_dcmio_P0\0", "x16_GenZ_to_2x8_dcmio_P1\0"}; |
| for (const auto& product_name : product_names_under_test) |
| { |
| const int product_name_offset = 19; |
| const int fru_size = 64; |
| std::vector<uint8_t> fruBytes = { |
| // Common Header (8 bytes) |
| 0x01, // Version |
| 0x00, // Internal offset |
| 0x00, // Chassis offset |
| 0x01, // Board offset |
| 0x00, // Product offset (*8 = 8) |
| 0x00, // Multirecord offset |
| 0x00, // Pad |
| 0xfe, // Header checksum |
| |
| // Board Area (starts at 8) |
| 0x01, // Format version |
| 0x07, // Area length (*8 = 56 bytes) |
| 0x19, // Language code (english) |
| 0x00, 0x00, 0x00, // MFG Date/Time |
| ((3 << 6) | 3), 'F', 'O', 'O', // Manufacturer: "FOO" |
| ((3 << 6) | 25), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, // Product Name (placeholder) |
| ((3 << 6) | 3), '7', '8', '9', // Serial Number |
| ((3 << 6) | 3), '1', '2', '3', // Part Number |
| ((3 << 6) | 3), 'D', 'E', 'F', // FRU Version ID |
| 0xc1, // end of fields |
| 0, 0, 0, 0, 0, 0, // padding |
| 0 // checksum placeholder |
| }; |
| fruBytes.resize(fru_size); |
| for (size_t idx = 0; idx < product_name.size(); idx++) |
| { |
| fruBytes[idx + product_name_offset] = product_name[idx]; |
| } |
| fruBytes[fru_size - 1] = calculateChecksum( |
| fruBytes.begin() + 8, fruBytes.begin() + fru_size - 1); |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["BOARD_PRODUCT_NAME"], product_name); |
| EXPECT_EQ(result["cxl_device"], "true"); |
| } |
| } |
| |
| TEST(FormatIPMIFRUTest, SupportBadAmphenolFruTest) |
| { |
| // This test specifically confirms support for known-bad Amphenol FRU |
| // information. |
| const int fru_size = 96; |
| std::vector<uint8_t> fruBytes = { |
| 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x0b, 0x19, 0x04, |
| 0xf4, 0xef, 0xc9, 0x41, 0x6d, 0x70, 0x68, 0x65, 0x6e, 0x6f, 0x6c, 0x00, |
| 0xc3, 0x50, 0x30, 0x00, 0xd6, 0x48, 0x47, 0x5a, 0x31, 0x36, 0x38, 0x2d, |
| 0x31, 0x33, 0x34, 0x36, 0x20, 0x32, 0x35, 0x34, 0x36, 0x30, 0x30, 0x33, |
| 0x31, 0x36, 0x00, 0xcb, 0x31, 0x31, 0x39, 0x36, 0x37, 0x37, 0x32, 0x2d, |
| 0x30, 0x32, 0x00, 0xc0, 0xd7, 0x01, 0x50, 0x43, 0x49, 0x65, 0x2d, 0x62, |
| 0x69, 0x66, 0x75, 0x72, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x78, |
| 0x38, 0x78, 0x38, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae}; |
| fruBytes.resize(fru_size); |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resOK); |
| EXPECT_EQ(result["BOARD_PRODUCT_NAME"], "P0"); |
| EXPECT_EQ(result["cxl_device"], "true"); |
| } |
| |
| TEST(FormatIPMIFRUTest, InvalidChecksumReturnsWarning) |
| { |
| std::vector<uint8_t> fruBytes = { |
| // Common Header |
| 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, |
| // Chassis Info Area |
| 0x01, 0x02, 0x03, 0xc1, |
| 0x00, // Invalid checksum |
| }; |
| std::map<std::string, std::string> result; |
| // The area is short, so it will cause a resErr instead of a resWarn. |
| // To properly test this, we need to provide a full area. |
| fruBytes.resize(8 + 2 * 8); |
| fruBytes[8 + 2 * 8 - 1] = 0; // set checksum to 0, which is likely wrong |
| |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resWarn); |
| } |
| |
| TEST(FormatIPMIFRUTest, TruncatedFruReturnsError) |
| { |
| const std::vector<uint8_t> fruBytes = { |
| // Common Header |
| 0x01, |
| 0x00, |
| 0x01, |
| 0x02, |
| 0x03, |
| 0x00, |
| 0x00, |
| 0xf9, |
| // Chassis Info Area (truncated) |
| 0x01, |
| 0x02, |
| 0x03, |
| }; |
| std::map<std::string, std::string> result; |
| EXPECT_EQ(formatIPMIFRU(fruBytes, result), resCodes::resErr); |
| } |