#include #include #include #include #include #include #include #include #include #include #include #include #include #include "msgbuf.h" #include constexpr auto hdrSize = sizeof(pldm_msg_hdr); TEST(DecodePackageHeaderInfo, goodPath) { // Package header identifier for Version 1.0.x constexpr std::array uuid{ 0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02}; // Package header version for DSP0267 version 1.0.x constexpr uint8_t pkgHeaderFormatRevision = 0x01; // Random PackageHeaderSize constexpr uint16_t pkgHeaderSize = 303; // PackageReleaseDateTime - "25/12/2021 00:00:00" std::array package_release_date_time{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00}; constexpr uint16_t componentBitmapBitLength = 8; // PackageVersionString constexpr std::string_view packageVersionStr{"OpenBMCv1.0"}; constexpr size_t packagerHeaderSize = sizeof(pldm_package_header_information) + packageVersionStr.size(); constexpr std::array packagerHeaderInfo{ 0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02, 0x01, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30}; pldm_package_header_information pkgHeader{}; variable_field packageVersion{}; auto rc = decode_pldm_package_header_info(packagerHeaderInfo.data(), packagerHeaderInfo.size(), &pkgHeader, &packageVersion); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(true, std::equal(pkgHeader.uuid, pkgHeader.uuid + PLDM_FWUP_UUID_LENGTH, uuid.begin(), uuid.end())); EXPECT_EQ(pkgHeader.package_header_format_version, pkgHeaderFormatRevision); EXPECT_EQ(pkgHeader.package_header_size, pkgHeaderSize); EXPECT_EQ(true, std::equal(pkgHeader.package_release_date_time, pkgHeader.package_release_date_time + PLDM_TIMESTAMP104_SIZE, package_release_date_time.begin(), package_release_date_time.end())); EXPECT_EQ(pkgHeader.component_bitmap_bit_length, componentBitmapBitLength); EXPECT_EQ(pkgHeader.package_version_string_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(pkgHeader.package_version_string_length, packageVersionStr.size()); std::string packageVersionString( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(packageVersion.ptr), packageVersion.length); EXPECT_EQ(packageVersionString, packageVersionStr); } TEST(DecodePackageHeaderInfo, errorPaths) { int rc = 0; constexpr std::string_view packageVersionStr{"OpenBMCv1.0"}; constexpr size_t packagerHeaderSize = sizeof(pldm_package_header_information) + packageVersionStr.size(); // Invalid Package Version String Type - 0x06 constexpr std::array invalidPackagerHeaderInfo1{ 0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x06, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30}; pldm_package_header_information packageHeader{}; variable_field packageVersion{}; rc = decode_pldm_package_header_info(nullptr, invalidPackagerHeaderInfo1.size(), &packageHeader, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo1.data(), invalidPackagerHeaderInfo1.size(), nullptr, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo1.data(), invalidPackagerHeaderInfo1.size(), &packageHeader, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pldm_package_header_info( invalidPackagerHeaderInfo1.data(), sizeof(pldm_package_header_information) - 1, &packageHeader, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo1.data(), invalidPackagerHeaderInfo1.size(), &packageHeader, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid Package Version String Length - 0x00 constexpr std::array invalidPackagerHeaderInfo2{ 0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30}; rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo2.data(), invalidPackagerHeaderInfo2.size(), &packageHeader, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Package version string length less than in the header information constexpr std::array invalidPackagerHeaderInfo3{ 0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e}; rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo3.data(), invalidPackagerHeaderInfo3.size(), &packageHeader, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); // ComponentBitmapBitLength not a multiple of 8 constexpr std::array invalidPackagerHeaderInfo4{ 0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x09, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30}; rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo4.data(), invalidPackagerHeaderInfo4.size(), &packageHeader, &packageVersion); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(DecodeFirmwareDeviceIdRecord, goodPath) { constexpr uint8_t descriptorCount = 1; // Continue component updates after failure constexpr std::bitset<32> deviceUpdateFlag{1}; constexpr uint16_t componentBitmapBitLength = 16; // Applicable Components - 1,2,5,8,9 std::vector> applicableComponentsBitfield{0x93, 0x01}; // ComponentImageSetVersionString constexpr std::string_view imageSetVersionStr{"VersionString1"}; // Initial descriptor - UUID constexpr std::array uuid{ 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b}; constexpr uint16_t fwDevicePkgDataLen = 2; // FirmwareDevicePackageData constexpr std::array fwDevicePkgData{0xab, 0xcd}; // Size of the firmware device ID record constexpr uint16_t recordLen = sizeof(pldm_firmware_device_id_record) + (componentBitmapBitLength / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) + imageSetVersionStr.size() + sizeof(pldm_descriptor_tlv) - 1 + uuid.size() + fwDevicePkgData.size(); // Firmware device ID record constexpr std::array record{ 0x31, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x02, 0x00, 0x93, 0x01, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x02, 0x00, 0x10, 0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b, 0xab, 0xcd}; pldm_firmware_device_id_record deviceIdRecHeader{}; variable_field applicableComponents{}; variable_field outCompImageSetVersionStr{}; variable_field recordDescriptors{}; variable_field outFwDevicePkgData{}; auto rc = decode_firmware_device_id_record( record.data(), record.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(deviceIdRecHeader.record_length, recordLen); EXPECT_EQ(deviceIdRecHeader.descriptor_count, descriptorCount); EXPECT_EQ(deviceIdRecHeader.device_update_option_flags.value, deviceUpdateFlag); EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_length, imageSetVersionStr.size()); EXPECT_EQ(deviceIdRecHeader.fw_device_pkg_data_length, fwDevicePkgDataLen); EXPECT_EQ(applicableComponents.length, applicableComponentsBitfield.size()); EXPECT_EQ(true, std::equal(applicableComponents.ptr, applicableComponents.ptr + applicableComponents.length, applicableComponentsBitfield.begin(), applicableComponentsBitfield.end())); EXPECT_EQ(outCompImageSetVersionStr.length, imageSetVersionStr.size()); std::string compImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outCompImageSetVersionStr.ptr), outCompImageSetVersionStr.length); EXPECT_EQ(compImageSetVersionStr, imageSetVersionStr); uint16_t descriptorType = 0; uint16_t descriptorLen = 0; variable_field descriptorData{}; // DescriptorCount is 1, so decode_descriptor_type_length_value called once rc = decode_descriptor_type_length_value(recordDescriptors.ptr, recordDescriptors.length, &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(recordDescriptors.length, sizeof(descriptorType) + sizeof(descriptorLen) + descriptorData.length); EXPECT_EQ(descriptorType, PLDM_FWUP_UUID); EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH); EXPECT_EQ(true, std::equal(descriptorData.ptr, descriptorData.ptr + descriptorData.length, uuid.begin(), uuid.end())); EXPECT_EQ(outFwDevicePkgData.length, fwDevicePkgData.size()); EXPECT_EQ(true, std::equal(outFwDevicePkgData.ptr, outFwDevicePkgData.ptr + outFwDevicePkgData.length, fwDevicePkgData.begin(), fwDevicePkgData.end())); } TEST(DecodeFirmwareDeviceIdRecord, goodPathNofwDevicePkgData) { constexpr uint8_t descriptorCount = 1; // Continue component updates after failure constexpr std::bitset<32> deviceUpdateFlag{1}; constexpr uint16_t componentBitmapBitLength = 8; // Applicable Components - 1,2 std::vector> applicableComponentsBitfield{0x03}; // ComponentImageSetVersionString constexpr std::string_view imageSetVersionStr{"VersionString1"}; // Initial descriptor - UUID constexpr std::array uuid{ 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b}; constexpr uint16_t fwDevicePkgDataLen = 0; // Size of the firmware device ID record constexpr uint16_t recordLen = sizeof(pldm_firmware_device_id_record) + (componentBitmapBitLength / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) + imageSetVersionStr.size() + sizeof(pldm_descriptor_tlv().descriptor_type) + sizeof(pldm_descriptor_tlv().descriptor_length) + uuid.size() + fwDevicePkgDataLen; // Firmware device ID record constexpr std::array record{ 0x2e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x03, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x02, 0x00, 0x10, 0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b}; pldm_firmware_device_id_record deviceIdRecHeader{}; variable_field applicableComponents{}; variable_field outCompImageSetVersionStr{}; variable_field recordDescriptors{}; variable_field outFwDevicePkgData{}; auto rc = decode_firmware_device_id_record( record.data(), record.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(deviceIdRecHeader.record_length, recordLen); EXPECT_EQ(deviceIdRecHeader.descriptor_count, descriptorCount); EXPECT_EQ(deviceIdRecHeader.device_update_option_flags.value, deviceUpdateFlag); EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_length, imageSetVersionStr.size()); EXPECT_EQ(deviceIdRecHeader.fw_device_pkg_data_length, 0); EXPECT_EQ(applicableComponents.length, applicableComponentsBitfield.size()); EXPECT_EQ(true, std::equal(applicableComponents.ptr, applicableComponents.ptr + applicableComponents.length, applicableComponentsBitfield.begin(), applicableComponentsBitfield.end())); EXPECT_EQ(outCompImageSetVersionStr.length, imageSetVersionStr.size()); std::string compImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outCompImageSetVersionStr.ptr), outCompImageSetVersionStr.length); EXPECT_EQ(compImageSetVersionStr, imageSetVersionStr); uint16_t descriptorType = 0; uint16_t descriptorLen = 0; variable_field descriptorData{}; // DescriptorCount is 1, so decode_descriptor_type_length_value called once rc = decode_descriptor_type_length_value(recordDescriptors.ptr, recordDescriptors.length, &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(recordDescriptors.length, sizeof(descriptorType) + sizeof(descriptorLen) + descriptorData.length); EXPECT_EQ(descriptorType, PLDM_FWUP_UUID); EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH); EXPECT_EQ(true, std::equal(descriptorData.ptr, descriptorData.ptr + descriptorData.length, uuid.begin(), uuid.end())); EXPECT_EQ(outFwDevicePkgData.ptr, nullptr); EXPECT_EQ(outFwDevicePkgData.length, 0); } TEST(DecodeFirmwareDeviceIdRecord, ErrorPaths) { constexpr uint16_t componentBitmapBitLength = 8; // Invalid ComponentImageSetVersionStringType constexpr std::array invalidRecord1{ 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00}; int rc = 0; pldm_firmware_device_id_record deviceIdRecHeader{}; variable_field applicableComponents{}; variable_field outCompImageSetVersionStr{}; variable_field recordDescriptors{}; variable_field outFwDevicePkgData{}; rc = decode_firmware_device_id_record( nullptr, invalidRecord1.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength, nullptr, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength, &deviceIdRecHeader, nullptr, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, nullptr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, nullptr, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size() - 1, componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength + 1, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_firmware_device_id_record( invalidRecord1.data(), invalidRecord1.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid ComponentImageSetVersionStringLength constexpr std::array invalidRecord2{ 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; rc = decode_firmware_device_id_record( invalidRecord2.data(), invalidRecord2.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // invalidRecord3 size is less than RecordLength constexpr std::array invalidRecord3{ 0x2e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00}; rc = decode_firmware_device_id_record( invalidRecord3.data(), invalidRecord3.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); // RecordLength is less than the calculated RecordLength constexpr std::array invalidRecord4{ 0x15, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x02, 0x00}; rc = decode_firmware_device_id_record( invalidRecord4.data(), invalidRecord4.size(), componentBitmapBitLength, &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors, &outFwDevicePkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(DecodeDescriptors, goodPath3Descriptors) { // In the descriptor data there are 3 descriptor entries // 1) IANA enterprise ID constexpr std::array iana{ 0x0a, 0x0b, 0x0c, 0xd}; // 2) UUID constexpr std::array uuid{ 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b}; // 3) Vendor Defined constexpr std::string_view vendorTitle{"OpenBMC"}; constexpr size_t vendorDescriptorLen = 2; constexpr std::array vendorDescriptorData{ 0x01, 0x02}; constexpr size_t vendorDefinedDescriptorLen = sizeof(pldm_vendor_defined_descriptor_title_data() .vendor_defined_descriptor_title_str_type) + sizeof(pldm_vendor_defined_descriptor_title_data() .vendor_defined_descriptor_title_str_len) + vendorTitle.size() + vendorDescriptorData.size(); constexpr size_t descriptorsLength = 3 * (sizeof(pldm_descriptor_tlv().descriptor_type) + sizeof(pldm_descriptor_tlv().descriptor_length)) + iana.size() + uuid.size() + vendorDefinedDescriptorLen; constexpr std::array descriptors{ 0x01, 0x00, 0x04, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x02, 0x00, 0x10, 0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b, 0xff, 0xff, 0x0b, 0x00, 0x01, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x01, 0x02}; size_t descriptorCount = 1; size_t descriptorsRemainingLength = descriptorsLength; int rc = 0; while (descriptorsRemainingLength && (descriptorCount <= 3)) { uint16_t descriptorType = 0; uint16_t descriptorLen = 0; variable_field descriptorData{}; rc = decode_descriptor_type_length_value( descriptors.data() + descriptorsLength - descriptorsRemainingLength, descriptorsRemainingLength, &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_SUCCESS); if (descriptorCount == 1) { EXPECT_EQ(descriptorType, PLDM_FWUP_IANA_ENTERPRISE_ID); EXPECT_EQ(descriptorData.length, PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH); EXPECT_EQ(true, std::equal(descriptorData.ptr, descriptorData.ptr + descriptorData.length, iana.begin(), iana.end())); } else if (descriptorCount == 2) { EXPECT_EQ(descriptorType, PLDM_FWUP_UUID); EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH); EXPECT_EQ(true, std::equal(descriptorData.ptr, descriptorData.ptr + descriptorData.length, uuid.begin(), uuid.end())); } else if (descriptorCount == 3) { EXPECT_EQ(descriptorType, PLDM_FWUP_VENDOR_DEFINED); EXPECT_EQ(descriptorData.length, vendorDefinedDescriptorLen); uint8_t descriptorTitleStrType = 0; variable_field descriptorTitleStr{}; variable_field vendorDefinedDescriptorData{}; rc = decode_vendor_defined_descriptor_value( descriptorData.ptr, descriptorData.length, &descriptorTitleStrType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(descriptorTitleStrType, PLDM_STR_TYPE_ASCII); EXPECT_EQ(descriptorTitleStr.length, vendorTitle.size()); std::string vendorTitleStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(descriptorTitleStr.ptr), descriptorTitleStr.length); EXPECT_EQ(vendorTitleStr, vendorTitle); EXPECT_EQ(vendorDefinedDescriptorData.length, vendorDescriptorData.size()); EXPECT_EQ(true, std::equal(vendorDefinedDescriptorData.ptr, vendorDefinedDescriptorData.ptr + vendorDefinedDescriptorData.length, vendorDescriptorData.begin(), vendorDescriptorData.end())); } descriptorsRemainingLength -= sizeof(descriptorType) + sizeof(descriptorLen) + descriptorData.length; descriptorCount++; } } TEST(DecodeDescriptors, errorPathDecodeDescriptorTLV) { int rc = 0; // IANA Enterprise ID descriptor length incorrect constexpr std::array invalidIANADescriptor1{ 0x01, 0x00, 0x03, 0x00, 0x0a, 0x0b, 0x0c}; uint16_t descriptorType = 0; variable_field descriptorData{}; rc = decode_descriptor_type_length_value(nullptr, invalidIANADescriptor1.size(), &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(), invalidIANADescriptor1.size(), nullptr, &descriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(), invalidIANADescriptor1.size(), &descriptorType, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_descriptor_type_length_value( invalidIANADescriptor1.data(), PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN - 1, &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(), invalidIANADescriptor1.size(), &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); // IANA Enterprise ID descriptor data less than length std::array invalidIANADescriptor2{0x01, 0x00, 0x04, 0x00, 0x0a, 0x0b, 0x0c}; rc = decode_descriptor_type_length_value(invalidIANADescriptor2.data(), invalidIANADescriptor2.size(), &descriptorType, &descriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(DecodeDescriptors, errorPathVendorDefinedDescriptor) { int rc = 0; // VendorDefinedDescriptorTitleStringType is invalid constexpr std::array invalidVendorDescriptor1{ 0x06, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43}; uint8_t descriptorStringType = 0; variable_field descriptorTitleStr{}; variable_field vendorDefinedDescriptorData{}; rc = decode_vendor_defined_descriptor_value( nullptr, invalidVendorDescriptor1.size(), &descriptorStringType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(), &descriptorStringType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(), nullptr, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(), &descriptorStringType, nullptr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(), &descriptorStringType, &descriptorTitleStr, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor1.data(), sizeof(pldm_vendor_defined_descriptor_title_data) - 1, &descriptorStringType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(), &descriptorStringType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // VendorDefinedDescriptorTitleStringLength is 0 std::array invalidVendorDescriptor2{ 0x01, 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43}; rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor2.data(), invalidVendorDescriptor2.size(), &descriptorStringType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // VendorDefinedDescriptorData not present in the data std::array invalidVendorDescriptor3{ 0x01, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43}; rc = decode_vendor_defined_descriptor_value( invalidVendorDescriptor3.data(), invalidVendorDescriptor3.size(), &descriptorStringType, &descriptorTitleStr, &vendorDefinedDescriptorData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(DecodeComponentImageInfo, goodPath) { // Firmware constexpr uint16_t compClassification = 16; constexpr uint16_t compIdentifier = 300; constexpr uint32_t compComparisonStamp = 0xffffffff; // Force update constexpr std::bitset<16> compOptions{1}; // System reboot[Bit position 3] & Medium-specific reset[Bit position 2] constexpr std::bitset<16> reqCompActivationMethod{0x0c}; // Random ComponentLocationOffset constexpr uint32_t compLocOffset = 357; // Random ComponentSize constexpr uint32_t compSize = 27; // ComponentVersionString constexpr std::string_view compVersionStr{"VersionString1"}; constexpr size_t compImageInfoSize = sizeof(pldm_component_image_information) + compVersionStr.size(); constexpr std::array compImageInfo{ 0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00, 0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31}; pldm_component_image_information outCompImageInfo{}; variable_field outCompVersionStr{}; auto rc = decode_pldm_comp_image_info(compImageInfo.data(), compImageInfo.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outCompImageInfo.comp_classification, compClassification); EXPECT_EQ(outCompImageInfo.comp_identifier, compIdentifier); EXPECT_EQ(outCompImageInfo.comp_comparison_stamp, compComparisonStamp); EXPECT_EQ(outCompImageInfo.comp_options.value, compOptions); EXPECT_EQ(outCompImageInfo.requested_comp_activation_method.value, reqCompActivationMethod); EXPECT_EQ(outCompImageInfo.comp_location_offset, compLocOffset); EXPECT_EQ(outCompImageInfo.comp_size, compSize); EXPECT_EQ(outCompImageInfo.comp_version_string_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(outCompImageInfo.comp_version_string_length, compVersionStr.size()); EXPECT_EQ(outCompVersionStr.length, outCompImageInfo.comp_version_string_length); std::string componentVersionString( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outCompVersionStr.ptr), outCompVersionStr.length); EXPECT_EQ(componentVersionString, compVersionStr); } TEST(DecodeComponentImageInfo, errorPaths) { int rc = 0; // ComponentVersionString constexpr std::string_view compVersionStr{"VersionString1"}; constexpr size_t compImageInfoSize = sizeof(pldm_component_image_information) + compVersionStr.size(); // Invalid ComponentVersionStringType - 0x06 constexpr std::array invalidCompImageInfo1{ 0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00, 0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31}; pldm_component_image_information outCompImageInfo{}; variable_field outCompVersionStr{}; rc = decode_pldm_comp_image_info(nullptr, invalidCompImageInfo1.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(), invalidCompImageInfo1.size(), nullptr, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(), invalidCompImageInfo1.size(), &outCompImageInfo, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(), sizeof(pldm_component_image_information) - 1, &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(), invalidCompImageInfo1.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid ComponentVersionStringLength - 0x00 constexpr std::array invalidCompImageInfo2{ 0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00, 0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31}; rc = decode_pldm_comp_image_info(invalidCompImageInfo2.data(), invalidCompImageInfo2.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Use Component Comparison Stamp is not set, but ComponentComparisonStamp // is not 0xffffffff constexpr std::array invalidCompImageInfo3{ 0x10, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31}; rc = decode_pldm_comp_image_info(invalidCompImageInfo3.data(), invalidCompImageInfo3.size() - 1, &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_pldm_comp_image_info(invalidCompImageInfo3.data(), invalidCompImageInfo3.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid ComponentLocationOffset - 0 constexpr std::array invalidCompImageInfo4{ 0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31}; rc = decode_pldm_comp_image_info(invalidCompImageInfo4.data(), invalidCompImageInfo4.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid ComponentSize - 0 constexpr std::array invalidCompImageInfo5{ 0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31}; rc = decode_pldm_comp_image_info(invalidCompImageInfo5.data(), invalidCompImageInfo5.size(), &outCompImageInfo, &outCompVersionStr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(QueryDeviceIdentifiers, goodPathEncodeRequest) { std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); uint8_t instanceId = 0x01; auto rc = encode_query_device_identifiers_req( instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, requestPtr); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST); EXPECT_EQ(requestPtr->hdr.instance_id, instanceId); EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP); EXPECT_EQ(requestPtr->hdr.command, PLDM_QUERY_DEVICE_IDENTIFIERS); } TEST(QueryDeviceIdentifiers, goodPathDecodeResponse) { // descriptorDataLen is not fixed here taking it as 6 constexpr uint8_t descriptorDataLen = 6; std::array responseMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto inResp = reinterpret_cast( responseMsg.data() + hdrSize); inResp->completion_code = PLDM_SUCCESS; inResp->device_identifiers_len = htole32(descriptorDataLen); inResp->descriptor_count = 1; // filling descriptor data std::fill_n(responseMsg.data() + hdrSize + sizeof(struct pldm_query_device_identifiers_resp), descriptorDataLen, 0xff); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); uint8_t completionCode = PLDM_SUCCESS; uint32_t deviceIdentifiersLen = 0; uint8_t descriptorCount = 0; uint8_t* outDescriptorData = nullptr; auto rc = decode_query_device_identifiers_resp( response, responseMsg.size() - hdrSize, &completionCode, &deviceIdentifiersLen, &descriptorCount, &outDescriptorData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(deviceIdentifiersLen, inResp->device_identifiers_len); EXPECT_EQ(descriptorCount, inResp->descriptor_count); EXPECT_EQ(true, std::equal(outDescriptorData, outDescriptorData + deviceIdentifiersLen, responseMsg.begin() + hdrSize + sizeof(struct pldm_query_device_identifiers_resp), responseMsg.end())); } TEST(GetFirmwareParameters, goodPathEncodeRequest) { std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); uint8_t instanceId = 0x01; auto rc = encode_get_firmware_parameters_req( instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, requestPtr); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST); EXPECT_EQ(requestPtr->hdr.instance_id, instanceId); EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP); EXPECT_EQ(requestPtr->hdr.command, PLDM_GET_FIRMWARE_PARAMETERS); } TEST(GetFirmwareParameters, decodeResponse) { // CapabilitiesDuringUpdate of the firmware device // Firmware device downgrade restrictions [Bit position 8] & // Firmware Device Partial Updates [Bit position 3] constexpr std::bitset<32> fdCapabilities{0x00000104}; constexpr uint16_t compCount = 1; constexpr std::string_view activeCompImageSetVersion{"VersionString1"}; constexpr std::string_view pendingCompImageSetVersion{"VersionString2"}; // constexpr uint16_t compClassification = 16; // constexpr uint16_t compIdentifier = 300; // constexpr uint8_t compClassificationIndex = 20; // constexpr uint32_t activeCompComparisonStamp = 0xabcdefab; // constexpr std::array activeComponentReleaseData = { // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; // constexpr uint32_t pendingCompComparisonStamp = 0x12345678; // constexpr std::array pendingComponentReleaseData = { // 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01}; constexpr std::string_view activeCompVersion{"VersionString3"}; constexpr std::string_view pendingCompVersion{"VersionString4"}; constexpr size_t compParamTableSize = sizeof(pldm_component_parameter_entry) + activeCompVersion.size() + pendingCompVersion.size(); constexpr std::array compParamTable{ 0x10, 0x00, 0x2c, 0x01, 0x14, 0xab, 0xef, 0xcd, 0xab, 0x01, 0x0e, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x78, 0x56, 0x34, 0x12, 0x01, 0x0e, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x33, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x34}; constexpr size_t getFwParamsPayloadLen = sizeof(pldm_get_firmware_parameters_resp) + activeCompImageSetVersion.size() + pendingCompImageSetVersion.size() + compParamTableSize; constexpr std::array getFwParamsResponse{ 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x10, 0x00, 0x2c, 0x01, 0x14, 0xab, 0xef, 0xcd, 0xab, 0x01, 0x0e, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x78, 0x56, 0x34, 0x12, 0x01, 0x0e, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x33, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x34}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getFwParamsResponse.data()); pldm_get_firmware_parameters_resp outResp{}; variable_field outActiveCompImageSetVersion{}; variable_field outPendingCompImageSetVersion{}; variable_field outCompParameterTable{}; auto rc = decode_get_firmware_parameters_resp( responseMsg, getFwParamsPayloadLen, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS); EXPECT_EQ(outResp.capabilities_during_update.value, fdCapabilities); EXPECT_EQ(outResp.comp_count, compCount); EXPECT_EQ(outResp.active_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(outResp.active_comp_image_set_ver_str_len, activeCompImageSetVersion.size()); EXPECT_EQ(outResp.pending_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(outResp.pending_comp_image_set_ver_str_len, pendingCompImageSetVersion.size()); std::string activeCompImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outActiveCompImageSetVersion.ptr), outActiveCompImageSetVersion.length); EXPECT_EQ(activeCompImageSetVersionStr, activeCompImageSetVersion); std::string pendingCompImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outPendingCompImageSetVersion.ptr), outPendingCompImageSetVersion.length); EXPECT_EQ(pendingCompImageSetVersionStr, pendingCompImageSetVersion); EXPECT_EQ(outCompParameterTable.length, compParamTableSize); EXPECT_EQ(true, std::equal(outCompParameterTable.ptr, outCompParameterTable.ptr + outCompParameterTable.length, compParamTable.begin(), compParamTable.end())); } TEST(GetFirmwareParameters, decodeResponseZeroCompCount) { // CapabilitiesDuringUpdate of the firmware device // FD Host Functionality during Firmware Update [Bit position 2] & // Component Update Failure Retry Capability [Bit position 1] constexpr std::bitset<32> fdCapabilities{0x06}; constexpr uint16_t compCount = 0; constexpr std::string_view activeCompImageSetVersion{"VersionString1"}; constexpr std::string_view pendingCompImageSetVersion{"VersionString2"}; constexpr size_t getFwParamsPayloadLen = sizeof(pldm_get_firmware_parameters_resp) + activeCompImageSetVersion.size() + pendingCompImageSetVersion.size(); constexpr std::array getFwParamsResponse{ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getFwParamsResponse.data()); pldm_get_firmware_parameters_resp outResp{}; variable_field outActiveCompImageSetVersion{}; variable_field outPendingCompImageSetVersion{}; variable_field outCompParameterTable{}; auto rc = decode_get_firmware_parameters_resp( responseMsg, getFwParamsPayloadLen, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS); EXPECT_EQ(outResp.capabilities_during_update.value, fdCapabilities); EXPECT_EQ(outResp.comp_count, compCount); EXPECT_EQ(outResp.active_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(outResp.active_comp_image_set_ver_str_len, activeCompImageSetVersion.size()); EXPECT_EQ(outResp.pending_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(outResp.pending_comp_image_set_ver_str_len, pendingCompImageSetVersion.size()); std::string activeCompImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outActiveCompImageSetVersion.ptr), outActiveCompImageSetVersion.length); EXPECT_EQ(activeCompImageSetVersionStr, activeCompImageSetVersion); std::string pendingCompImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outPendingCompImageSetVersion.ptr), outPendingCompImageSetVersion.length); EXPECT_EQ(pendingCompImageSetVersionStr, pendingCompImageSetVersion); EXPECT_EQ(outCompParameterTable.ptr, nullptr); EXPECT_EQ(outCompParameterTable.length, 0); } TEST(GetFirmwareParameters, decodeResponseNoPendingCompImageVersionStrZeroCompCount) { // CapabilitiesDuringUpdate of the firmware device // FD Host Functionality during Firmware Update [Bit position 2] & // Component Update Failure Retry Capability [Bit position 1] constexpr std::bitset<32> fdCapabilities{0x06}; constexpr uint16_t compCount = 0; constexpr std::string_view activeCompImageSetVersion{"VersionString"}; constexpr size_t getFwParamsPayloadLen = sizeof(pldm_get_firmware_parameters_resp) + activeCompImageSetVersion.size(); constexpr std::array getFwParamsResponse{0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getFwParamsResponse.data()); pldm_get_firmware_parameters_resp outResp{}; variable_field outActiveCompImageSetVersion{}; variable_field outPendingCompImageSetVersion{}; variable_field outCompParameterTable{}; auto rc = decode_get_firmware_parameters_resp( responseMsg, getFwParamsPayloadLen, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS); EXPECT_EQ(outResp.capabilities_during_update.value, fdCapabilities); EXPECT_EQ(outResp.comp_count, compCount); EXPECT_EQ(outResp.active_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(outResp.active_comp_image_set_ver_str_len, activeCompImageSetVersion.size()); EXPECT_EQ(outResp.pending_comp_image_set_ver_str_type, PLDM_STR_TYPE_UNKNOWN); EXPECT_EQ(outResp.pending_comp_image_set_ver_str_len, 0); std::string activeCompImageSetVersionStr( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(outActiveCompImageSetVersion.ptr), outActiveCompImageSetVersion.length); EXPECT_EQ(activeCompImageSetVersionStr, activeCompImageSetVersion); EXPECT_EQ(outPendingCompImageSetVersion.ptr, nullptr); EXPECT_EQ(outPendingCompImageSetVersion.length, 0); EXPECT_EQ(outCompParameterTable.ptr, nullptr); EXPECT_EQ(outCompParameterTable.length, 0); } TEST(GetFirmwareParameters, decodeResponseErrorCompletionCode) { constexpr std::array getFwParamsResponse{0x00, 0x00, 0x00, 0x01}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getFwParamsResponse.data()); pldm_get_firmware_parameters_resp outResp{}; variable_field outActiveCompImageSetVersion{}; variable_field outPendingCompImageSetVersion{}; variable_field outCompParameterTable{}; auto rc = decode_get_firmware_parameters_resp( responseMsg, getFwParamsResponse.size(), &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outResp.completion_code, PLDM_ERROR); } TEST(GetFirmwareParameters, errorPathdecodeResponse) { int rc = 0; // Invalid ActiveComponentImageSetVersionStringType constexpr std::array invalidGetFwParamsResponse1{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(invalidGetFwParamsResponse1.data()); pldm_get_firmware_parameters_resp outResp{}; variable_field outActiveCompImageSetVersion{}; variable_field outPendingCompImageSetVersion{}; variable_field outCompParameterTable{}; rc = decode_get_firmware_parameters_resp( nullptr, invalidGetFwParamsResponse1.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, nullptr, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp, nullptr, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, nullptr, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_firmware_parameters_resp( responseMsg, 0, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse1.size() - 1 - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid ActiveComponentImageSetVersionStringLength constexpr std::array invalidGetFwParamsResponse2{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(invalidGetFwParamsResponse2.data()); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse2.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid PendingComponentImageSetVersionStringType & // PendingComponentImageSetVersionStringLength constexpr std::array invalidGetFwParamsResponse3{ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x00}; responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(invalidGetFwParamsResponse3.data()); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse3.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Invalid PendingComponentImageSetVersionStringType & // PendingComponentImageSetVersionStringLength constexpr std::array invalidGetFwParamsResponse4{ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x06, 0x0e}; responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(invalidGetFwParamsResponse4.data()); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse4.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Total payload length less than expected constexpr std::array invalidGetFwParamsResponse5{ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x0e}; responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(invalidGetFwParamsResponse5.data()); rc = decode_get_firmware_parameters_resp( responseMsg, invalidGetFwParamsResponse5.size() - hdrSize, &outResp, &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, &outCompParameterTable); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(GetFirmwareParameters, goodPathDecodeComponentParameterEntry) { // Random value for component classification constexpr uint16_t compClassification = 0x0a0b; // Random value for component classification constexpr uint16_t compIdentifier = 0x0c0d; // Random value for component classification constexpr uint32_t timestamp = 0x12345678; // Random value for component activation methods constexpr uint16_t compActivationMethods = 0xbbdd; // Random value for capabilities during update constexpr uint32_t capabilitiesDuringUpdate = 0xbadbeefe; // ActiveCompImageSetVerStrLen is not fixed here taking it as 8 constexpr uint8_t activeCompVerStrLen = 8; // PendingCompImageSetVerStrLen is not fixed here taking it as 8 constexpr uint8_t pendingCompVerStrLen = 8; constexpr size_t entryLength = sizeof(struct pldm_component_parameter_entry) + activeCompVerStrLen + pendingCompVerStrLen; std::array entry{}; auto inEntry = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(entry.data()); inEntry->comp_classification = htole16(compClassification); inEntry->comp_identifier = htole16(compIdentifier); inEntry->comp_classification_index = 0x0f; inEntry->active_comp_comparison_stamp = htole32(timestamp); inEntry->active_comp_ver_str_type = 1; inEntry->active_comp_ver_str_len = activeCompVerStrLen; std::fill_n(inEntry->active_comp_release_date, sizeof(inEntry->active_comp_release_date), 0xff); inEntry->pending_comp_comparison_stamp = htole32(timestamp); inEntry->pending_comp_ver_str_type = 1; inEntry->pending_comp_ver_str_len = pendingCompVerStrLen; std::fill_n(inEntry->pending_comp_release_date, sizeof(inEntry->pending_comp_release_date), 0xff); inEntry->comp_activation_methods.value = htole16(compActivationMethods); inEntry->capabilities_during_update.value = htole32(capabilitiesDuringUpdate); constexpr auto activeCompVerStrPos = sizeof(struct pldm_component_parameter_entry); std::fill_n(entry.data() + activeCompVerStrPos, activeCompVerStrLen, 0xaa); constexpr auto pendingCompVerStrPos = activeCompVerStrPos + activeCompVerStrLen; std::fill_n(entry.data() + pendingCompVerStrPos, pendingCompVerStrLen, 0xbb); struct pldm_component_parameter_entry outEntry; struct variable_field outActiveCompVerStr; struct variable_field outPendingCompVerStr; auto rc = decode_get_firmware_parameters_resp_comp_entry( entry.data(), entryLength, &outEntry, &outActiveCompVerStr, &outPendingCompVerStr); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outEntry.comp_classification, compClassification); EXPECT_EQ(outEntry.comp_identifier, compIdentifier); EXPECT_EQ(inEntry->comp_classification_index, outEntry.comp_classification_index); EXPECT_EQ(outEntry.active_comp_comparison_stamp, timestamp); EXPECT_EQ(inEntry->active_comp_ver_str_type, outEntry.active_comp_ver_str_type); EXPECT_EQ(inEntry->active_comp_ver_str_len, outEntry.active_comp_ver_str_len); EXPECT_EQ(0, memcmp(inEntry->active_comp_release_date, outEntry.active_comp_release_date, sizeof(inEntry->active_comp_release_date))); EXPECT_EQ(outEntry.pending_comp_comparison_stamp, timestamp); EXPECT_EQ(inEntry->pending_comp_ver_str_type, outEntry.pending_comp_ver_str_type); EXPECT_EQ(inEntry->pending_comp_ver_str_len, outEntry.pending_comp_ver_str_len); EXPECT_EQ(0, memcmp(inEntry->pending_comp_release_date, outEntry.pending_comp_release_date, sizeof(inEntry->pending_comp_release_date))); EXPECT_EQ(outEntry.comp_activation_methods.value, compActivationMethods); EXPECT_EQ(outEntry.capabilities_during_update.value, capabilitiesDuringUpdate); EXPECT_EQ(0, memcmp(outActiveCompVerStr.ptr, entry.data() + activeCompVerStrPos, outActiveCompVerStr.length)); EXPECT_EQ(0, memcmp(outPendingCompVerStr.ptr, entry.data() + pendingCompVerStrPos, outPendingCompVerStr.length)); } #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamDevices, goodPathEncodeRequest) { constexpr uint8_t instanceId = 1; std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); auto rc = encode_query_downstream_devices_req(instanceId, requestPtr); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST); EXPECT_EQ(requestPtr->hdr.instance_id, instanceId); EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP); EXPECT_EQ(requestPtr->hdr.command, PLDM_QUERY_DOWNSTREAM_DEVICES); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamDevices, encodeRequestInvalidData) { constexpr uint8_t instanceId = 1; auto rc = encode_query_downstream_devices_req(instanceId, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamDevices, goodPathDecodeResponse) { uint8_t completion_code_resp = PLDM_SUCCESS; uint8_t downstream_device_update_supported_resp = PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED; uint16_t number_of_downstream_devices_resp = 1; uint16_t max_number_of_downstream_devices_resp = 1; /** Capabilities of updating downstream devices * FDP supports downstream devices dynamically attached [Bit position 0] & * FDP supports downstream devices dynamically removed [Bit position 1] */ bitfield32_t capabilities_resp = {.value = 0x0002}; int rc; std::array responseMsg{}; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_cc(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, PLDM_SUCCESS); pldm_msgbuf_insert_uint8(buf, completion_code_resp); pldm_msgbuf_insert_uint8(buf, downstream_device_update_supported_resp); pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp); pldm_msgbuf_insert_uint16(buf, max_number_of_downstream_devices_resp); pldm_msgbuf_insert_uint32(buf, capabilities_resp.value); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_devices_resp resp_data; rc = decode_query_downstream_devices_resp( response, responseMsg.size() - hdrSize, &resp_data); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(resp_data.completion_code, completion_code_resp); EXPECT_EQ(resp_data.downstream_device_update_supported, downstream_device_update_supported_resp); EXPECT_EQ(resp_data.number_of_downstream_devices, number_of_downstream_devices_resp); EXPECT_EQ(resp_data.max_number_of_downstream_devices, max_number_of_downstream_devices_resp); EXPECT_EQ(resp_data.capabilities.value, capabilities_resp.value); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamDevices, decodeRequestUndefinedValue) { uint8_t completion_code_resp = PLDM_SUCCESS; uint8_t downstream_device_update_supported_resp = 0xe; /*Undefined value*/ uint16_t number_of_downstream_devices_resp = 1; uint16_t max_number_of_downstream_devices_resp = 1; /** Capabilities of updating downstream devices * FDP supports downstream devices dynamically attached [Bit position 0] & * FDP supports downstream devices dynamically removed [Bit position 1] */ bitfield32_t capabilities_resp = {.value = 0x0002}; int rc; std::array responseMsg{}; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_cc(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, PLDM_SUCCESS); pldm_msgbuf_insert_uint8(buf, completion_code_resp); pldm_msgbuf_insert_uint8(buf, downstream_device_update_supported_resp); pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp); pldm_msgbuf_insert_uint16(buf, max_number_of_downstream_devices_resp); pldm_msgbuf_insert_uint32(buf, capabilities_resp.value); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_devices_resp resp_data; rc = decode_query_downstream_devices_resp( response, responseMsg.size() - hdrSize, &resp_data); ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamDevices, decodeRequestErrorBufSize) { uint8_t completion_code_resp = PLDM_SUCCESS; uint8_t downstream_device_update_supported_resp = PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED; uint16_t number_of_downstream_devices_resp = 1; uint16_t max_number_of_downstream_devices_resp = 1; /** Capabilities of updating downstream devices * FDP supports downstream devices dynamically attached [Bit position 0] & * FDP supports downstream devices dynamically removed [Bit position 1] */ bitfield32_t capabilities_resp = {.value = 0x0002}; int rc; std::array responseMsg{}; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_cc(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, PLDM_SUCCESS); pldm_msgbuf_insert_uint8(buf, completion_code_resp); pldm_msgbuf_insert_uint8(buf, downstream_device_update_supported_resp); pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp); pldm_msgbuf_insert_uint16(buf, max_number_of_downstream_devices_resp); // Inject error value pldm_msgbuf_insert_uint16(buf, (uint16_t)capabilities_resp.value); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_devices_resp resp_data; rc = decode_query_downstream_devices_resp( response, responseMsg.size() - hdrSize, &resp_data); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamIdentifiers, goodPathEncodeRequest) { constexpr uint8_t instanceId = 1; constexpr uint32_t dataTransferHandle = 0xFFFFFFFF; constexpr enum transfer_op_flag transferOperationFlag = PLDM_GET_FIRSTPART; constexpr size_t payload_length = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES; std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); auto rc = encode_query_downstream_identifiers_req( instanceId, dataTransferHandle, transferOperationFlag, requestPtr, payload_length); EXPECT_EQ(rc, PLDM_SUCCESS); std::array expectedReq{0x81, 0x05, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0x01}; EXPECT_EQ(requestMsg, expectedReq); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamIdentifiers, encodeRequestInvalidErrorPaths) { constexpr uint8_t instanceId = 1; constexpr uint32_t dataTransferHandle = 0x0; constexpr enum transfer_op_flag transferOperationFlag = PLDM_GET_FIRSTPART; constexpr enum transfer_op_flag invalidTransferOperationFlag = PLDM_ACKNOWLEDGEMENT_ONLY; constexpr size_t payload_length = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES; std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); auto rc = encode_query_downstream_identifiers_req( instanceId, dataTransferHandle, transferOperationFlag, nullptr, payload_length); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_query_downstream_identifiers_req( instanceId, dataTransferHandle, transferOperationFlag, requestPtr, payload_length - 1); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = encode_query_downstream_identifiers_req(instanceId, dataTransferHandle, invalidTransferOperationFlag, requestPtr, payload_length); EXPECT_EQ(rc, PLDM_INVALID_TRANSFER_OPERATION_FLAG); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamIdentifiers, goodPathDecodeResponse) { // Len is not fixed here taking it as 9, contains 1 downstream device with // 1 descriptor constexpr uint32_t downstreamDevicesLen = 9; constexpr uint8_t complition_code_resp = PLDM_SUCCESS; constexpr uint32_t next_data_transfer_handle_resp = 0x0; constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END; const uint32_t downstream_devices_length_resp = htole32(downstreamDevicesLen); constexpr uint16_t number_of_downstream_devices_resp = 1; std::array responseMsg{}; int rc = 0; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_cc(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, PLDM_SUCCESS); pldm_msgbuf_insert_uint8(buf, complition_code_resp); pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp); pldm_msgbuf_insert_uint8(buf, transfer_flag_resp); pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp); pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp); /** Filling descriptor data, the correctness of the downstream devices data * is not checked in this test case so filling with 0xff */ std::fill_n(responseMsg.data() + hdrSize + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN, downstreamDevicesLen, 0xff); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_identifiers_resp resp_data = {}; struct variable_field downstreamDevices = {}; rc = decode_query_downstream_identifiers_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDevices); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(resp_data.completion_code, complition_code_resp); EXPECT_EQ(resp_data.next_data_transfer_handle, next_data_transfer_handle_resp); EXPECT_EQ(resp_data.transfer_flag, transfer_flag_resp); EXPECT_EQ(resp_data.downstream_devices_length, downstream_devices_length_resp); EXPECT_EQ(resp_data.number_of_downstream_devices, number_of_downstream_devices_resp); EXPECT_EQ(downstreamDevices.length, downstreamDevicesLen); EXPECT_EQ(true, std::equal(downstreamDevices.ptr, downstreamDevices.ptr + downstreamDevices.length, responseMsg.begin() + hdrSize + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN, responseMsg.end())); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamIdentifiers, decodeRequestErrorPaths) { std::array responseMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_identifiers_resp resp_data = {}; struct variable_field downstreamDevices = {}; // Test nullptr auto rc = decode_query_downstream_identifiers_resp( nullptr, responseMsg.size() - hdrSize, nullptr, &downstreamDevices); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // Test not PLDM_SUCCESS completion code response->payload[0] = PLDM_ERROR_UNSUPPORTED_PLDM_CMD; rc = decode_query_downstream_identifiers_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDevices); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(resp_data.completion_code, PLDM_ERROR_UNSUPPORTED_PLDM_CMD); // Test payload length less than minimum length response->payload[0] = PLDM_SUCCESS; rc = decode_query_downstream_identifiers_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDevices); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamIdentifiers, decodeRequestErrorDownstreamDevicesSize) { // Len is not fixed here taking it as 9, contains 1 downstream device with // 1 descriptor constexpr uint32_t actualDownstreamDevicesLen = 9; constexpr uint8_t complition_code_resp = PLDM_SUCCESS; constexpr uint32_t next_data_transfer_handle_resp = 0x0; constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END; const uint32_t downstream_devices_length_resp = htole32(actualDownstreamDevicesLen + 1 /* inject error length*/); constexpr uint16_t number_of_downstream_devices_resp = 1; std::array responseMsg{}; int rc = 0; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_cc(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, PLDM_SUCCESS); pldm_msgbuf_insert_uint8(buf, complition_code_resp); pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp); pldm_msgbuf_insert_uint8(buf, transfer_flag_resp); pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp); pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp); /** Filling descriptor data, the correctness of the downstream devices data * is not checked in this test case so filling with 0xff */ std::fill_n(responseMsg.data() + hdrSize + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN, actualDownstreamDevicesLen, 0xff); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_identifiers_resp resp_data = {}; struct variable_field downstreamDevices = {}; /** In test mode, this will trigger an assert failure and cause the unit * test to fail if only testing by the rc. Use ASSERT_DEATH to test this * scenario. * * The 1st parameter is the function under test. * The 2nd parameter compares the output of the program. */ #ifdef NDEBUG EXPECT_NE(decode_query_downstream_identifiers_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDevices), PLDM_SUCCESS); #else EXPECT_DEATH( decode_query_downstream_identifiers_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDevices), // This error doesn't output any error message, leave it be empty ""); #endif } #endif #ifdef LIBPLDM_API_TESTING TEST(QueryDownstreamIdentifiers, decodeRequestErrorBufSize) { constexpr uint32_t actualDownstreamDevicesLen = 0; constexpr uint16_t number_of_downstream_devices_resp = 1; constexpr uint8_t complition_code_resp = PLDM_SUCCESS; constexpr uint32_t next_data_transfer_handle_resp = 0x0; constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END; const uint32_t downstream_devices_length_resp = htole32(actualDownstreamDevicesLen); std::array responseMsg{}; int rc = 0; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_cc(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, PLDM_SUCCESS); pldm_msgbuf_insert_uint8(buf, complition_code_resp); pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp); pldm_msgbuf_insert_uint8(buf, transfer_flag_resp); pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp); // Inject error buffer size pldm_msgbuf_insert_uint8(buf, (uint8_t)number_of_downstream_devices_resp); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_query_downstream_identifiers_resp resp_data = {}; struct variable_field downstreamDevices = {}; rc = decode_query_downstream_identifiers_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDevices); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, goodPathEncodeRequest) { constexpr uint8_t instanceId = 1; constexpr uint32_t dataTransferHandle = 0x0; constexpr enum transfer_op_flag transferOperationFlag = PLDM_GET_FIRSTPART; constexpr size_t payload_length = PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES; std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); auto rc = encode_get_downstream_firmware_params_req( instanceId, dataTransferHandle, transferOperationFlag, requestPtr, payload_length); EXPECT_EQ(rc, 0); std::array expectedReq{0x81, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01}; EXPECT_EQ(requestMsg, expectedReq); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, encodeRequestInvalidTransferOperationFlag) { constexpr uint8_t instanceId = 1; constexpr uint32_t dataTransferHandle = 0x0; // Setup invalid transfer operation flag constexpr enum transfer_op_flag transferOperationFlag = PLDM_ACKNOWLEDGEMENT_ONLY; constexpr size_t payload_length = PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES; std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); auto rc = encode_get_downstream_firmware_params_req( instanceId, dataTransferHandle, transferOperationFlag, requestPtr, payload_length); EXPECT_EQ(rc, -EBADMSG); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, encodeRequestErrorBufSize) { constexpr uint8_t instanceId = 1; constexpr uint32_t dataTransferHandle = 0x0; // Setup invalid transfer operation flag constexpr enum transfer_op_flag transferOperationFlag = PLDM_ACKNOWLEDGEMENT_ONLY; constexpr size_t payload_length = PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES - 1 /* inject erro length*/; std::array requestMsg{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestPtr = reinterpret_cast(requestMsg.data()); auto rc = encode_get_downstream_firmware_params_req( instanceId, dataTransferHandle, transferOperationFlag, requestPtr, payload_length); EXPECT_EQ(rc, -EOVERFLOW); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, goodPathDecodeResponse) { /** Count is not fixed here taking it as 1, and the downstream device's * version strings length are set to 8 */ constexpr uint16_t downstreamDeviceCount = 1; constexpr uint8_t activeComponentVersionStringLength = 8; constexpr uint8_t pendingComponentVersionStringLength = 8; constexpr size_t downstreamDeviceParamTableLen = sizeof(pldm_component_parameter_entry) + activeComponentVersionStringLength + pendingComponentVersionStringLength; constexpr uint8_t complition_code_resp = PLDM_SUCCESS; constexpr uint32_t next_data_transfer_handle_resp = 0x0; constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END; constexpr bitfield32_t fdp_capabilities_during_update = {.value = 0x0002}; std::array responseMsg{}; int rc = 0; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_errno(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, 0); pldm_msgbuf_insert_uint8(buf, complition_code_resp); pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp); pldm_msgbuf_insert_uint8(buf, transfer_flag_resp); pldm_msgbuf_insert_uint32(buf, fdp_capabilities_during_update.value); pldm_msgbuf_insert_uint16(buf, downstreamDeviceCount); /** Filling paramter table, the correctness of the downstream devices data * is not checked in this test case so filling with 0xff */ std::fill_n(responseMsg.data() + hdrSize + PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN, downstreamDeviceParamTableLen, 0xff); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto table = reinterpret_cast( responseMsg.data() + hdrSize + PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN); table->active_comp_ver_str_len = activeComponentVersionStringLength; table->pending_comp_ver_str_len = pendingComponentVersionStringLength; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_get_downstream_firmware_params_resp resp_data = {}; struct variable_field downstreamDeviceParamTable = {}; rc = decode_get_downstream_firmware_params_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDeviceParamTable); EXPECT_EQ(rc, 0); EXPECT_EQ(resp_data.completion_code, complition_code_resp); EXPECT_EQ(resp_data.next_data_transfer_handle, next_data_transfer_handle_resp); EXPECT_EQ(resp_data.transfer_flag, transfer_flag_resp); EXPECT_EQ(resp_data.downstream_device_count, downstreamDeviceCount); EXPECT_EQ(downstreamDeviceParamTable.length, downstreamDeviceParamTableLen); EXPECT_EQ(true, std::equal(downstreamDeviceParamTable.ptr, downstreamDeviceParamTable.ptr + downstreamDeviceParamTable.length, responseMsg.begin() + hdrSize + PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN, responseMsg.end())); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, decodeResponseInvalidLength) { /** Count is not fixed here taking it as 1, and the downstream device's * version strings length are set to 8 */ constexpr uint16_t downstreamDeviceCount = 1; constexpr uint8_t activeComponentVersionStringLength = 8; constexpr uint8_t pendingComponentVersionStringLength = 8; constexpr size_t downstreamDeviceParamTableLen = PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN + activeComponentVersionStringLength + pendingComponentVersionStringLength; constexpr uint8_t complition_code_resp = PLDM_SUCCESS; constexpr uint32_t next_data_transfer_handle_resp = 0x0; constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END; constexpr bitfield32_t fdp_capabilities_during_update = {.value = 0x0002}; std::array responseMsg{}; int rc = 0; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_errno(buf, 0, responseMsg.data() + hdrSize, responseMsg.size() - hdrSize); EXPECT_EQ(rc, 0); pldm_msgbuf_insert_uint8(buf, complition_code_resp); pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp); pldm_msgbuf_insert_uint8(buf, transfer_flag_resp); pldm_msgbuf_insert_uint32(buf, fdp_capabilities_during_update.value); pldm_msgbuf_insert_uint16(buf, downstreamDeviceCount); /** Filling paramter table, the correctness of the downstream devices data * is not checked in this test case so filling with 0xff */ std::fill_n(responseMsg.data() + hdrSize + PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN, downstreamDeviceParamTableLen - 1 /* inject error length*/, 0xff); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto response = reinterpret_cast(responseMsg.data()); struct pldm_get_downstream_firmware_params_resp resp_data = {}; struct variable_field downstreamDeviceParamTable = {}; rc = decode_get_downstream_firmware_params_resp( response, responseMsg.size() - hdrSize, &resp_data, &downstreamDeviceParamTable); EXPECT_EQ(rc, 0); pldm_downstream_device_parameter_entry entry{}; variable_field versions{}; /** In test mode, this will trigger an assert failure and cause the unit * test to fail if only testing by the rc. Use ASSERT_DEATH to test this * scenario. * * The 1st parameter is the function under test. * The 2nd parameter compares the output of the program. */ #ifdef NDEBUG EXPECT_NE(decode_downstream_device_parameter_table_entry( &downstreamDeviceParamTable, &entry, &versions), 0); #else EXPECT_DEATH( decode_downstream_device_parameter_table_entry( &downstreamDeviceParamTable, &entry, &versions), // This error doesn't output any error message, leave it be empty ""); #endif } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, goodPathDecodeDownstreamDeviceParamTable) { // Arbitrary downstream device index constexpr uint16_t downstreamDeviceIndex = 1; // Arbitrary value for component classification constexpr uint32_t comparisonStamp = 0x12345678; // Arbitrary value for component activation methods constexpr uint16_t compActivationMethods = 0xbbdd; // Arbitrary value for capabilities during update constexpr uint32_t capabilitiesDuringUpdate = 0xbadbeefe; // ActiveCompImageSetVerStrLen is not fixed here taking it as 8 constexpr uint8_t activeCompVerStrLen = 8; // PendingCompImageSetVerStrLen is not fixed here taking it as 8 constexpr uint8_t pendingCompVerStrLen = 8; // Arbitrary value for release date constexpr char release_date[8] = {'2', '0', '2', '4', '0', '6', '2', '1'}; // Arbitrary version strings constexpr char activeCompVerStr[activeCompVerStrLen] = {'1', '2', '3', '4', '5', '6', '7', '8'}; constexpr char pendingCompVerStr[pendingCompVerStrLen] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; std::array responseMsg{}; int rc = 0; struct pldm_msgbuf _buf; struct pldm_msgbuf* buf = &_buf; rc = pldm_msgbuf_init_errno(buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, responseMsg.data(), responseMsg.size()); EXPECT_EQ(rc, 0); pldm_msgbuf_insert_uint16(buf, downstreamDeviceIndex); pldm_msgbuf_insert_uint32(buf, comparisonStamp); pldm_msgbuf_insert_uint8(buf, (uint8_t)PLDM_STR_TYPE_ASCII); pldm_msgbuf_insert_uint8(buf, activeCompVerStrLen); rc = pldm_msgbuf_insert_array_char(buf, sizeof(release_date), release_date, sizeof(release_date)); ASSERT_EQ(rc, 0); pldm_msgbuf_insert_uint32(buf, comparisonStamp); pldm_msgbuf_insert_uint8(buf, (uint8_t)PLDM_STR_TYPE_ASCII); pldm_msgbuf_insert_uint8(buf, pendingCompVerStrLen); rc = pldm_msgbuf_insert_array_char(buf, sizeof(release_date), release_date, sizeof(release_date)); ASSERT_EQ(rc, 0); pldm_msgbuf_insert_uint16(buf, compActivationMethods); pldm_msgbuf_insert_uint32(buf, capabilitiesDuringUpdate); rc = pldm_msgbuf_insert_array_char( buf, activeCompVerStrLen, activeCompVerStr, sizeof(activeCompVerStr)); ASSERT_EQ(rc, 0); rc = pldm_msgbuf_insert_array_char(buf, pendingCompVerStrLen, pendingCompVerStr, sizeof(pendingCompVerStr)); ASSERT_EQ(rc, 0); variable_field rawData = {.ptr = responseMsg.data(), .length = responseMsg.size()}; struct pldm_downstream_device_parameter_entry_versions entry_version = {}; struct variable_field versions = {}; const uint8_t* original_ptr = rawData.ptr; rc = decode_downstream_device_parameter_table_entry( &rawData, &entry_version.entry, &versions); EXPECT_EQ(rc, 0); EXPECT_EQ(rawData.ptr, original_ptr + PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN + entry_version.entry.active_comp_ver_str_len + entry_version.entry.pending_comp_ver_str_len); EXPECT_EQ(rawData.length, 0); // Further decode the version strings rc = decode_downstream_device_parameter_table_entry_versions( &versions, &entry_version.entry, entry_version.active_comp_ver_str, entry_version.pending_comp_ver_str); struct pldm_downstream_device_parameter_entry entry = entry_version.entry; EXPECT_EQ(rc, 0); // Verify the decoded table entry EXPECT_EQ(entry.downstream_device_index, downstreamDeviceIndex); EXPECT_EQ(entry.active_comp_comparison_stamp, comparisonStamp); EXPECT_EQ(entry.active_comp_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(entry.active_comp_ver_str_len, activeCompVerStrLen); EXPECT_EQ(0, memcmp(entry.active_comp_release_date, release_date, sizeof(release_date))); EXPECT_EQ(entry.pending_comp_comparison_stamp, comparisonStamp); EXPECT_EQ(entry.pending_comp_ver_str_type, PLDM_STR_TYPE_ASCII); EXPECT_EQ(entry.pending_comp_ver_str_len, pendingCompVerStrLen); EXPECT_EQ(0, memcmp(entry.pending_comp_release_date, release_date, sizeof(release_date))); EXPECT_EQ(entry.comp_activation_methods.value, compActivationMethods); EXPECT_EQ(entry.capabilities_during_update.value, capabilitiesDuringUpdate); EXPECT_EQ(entry.active_comp_ver_str_len + entry.pending_comp_ver_str_len, versions.length); EXPECT_EQ(0, memcmp(versions.ptr, activeCompVerStr, activeCompVerStrLen)); EXPECT_EQ(0, memcmp(versions.ptr + entry.active_comp_ver_str_len, pendingCompVerStr, pendingCompVerStrLen)); // Verify version strings EXPECT_EQ(0, memcmp(entry_version.entry.active_comp_ver_str, activeCompVerStr, activeCompVerStrLen)); EXPECT_EQ('\0', entry_version.entry.active_comp_ver_str[activeCompVerStrLen]); EXPECT_EQ(0, memcmp(entry_version.entry.pending_comp_ver_str, pendingCompVerStr, pendingCompVerStrLen)); EXPECT_EQ('\0', entry_version.entry.pending_comp_ver_str[pendingCompVerStrLen]); EXPECT_EQ(0, memcmp(entry_version.active_comp_ver_str, activeCompVerStr, activeCompVerStrLen)); EXPECT_EQ('\0', entry_version.active_comp_ver_str[activeCompVerStrLen]); EXPECT_EQ(0, memcmp(entry_version.pending_comp_ver_str, pendingCompVerStr, pendingCompVerStrLen)); EXPECT_EQ('\0', entry_version.pending_comp_ver_str[pendingCompVerStrLen]); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, goodPathDecodeDownstreamTableVersions) { // Arbitrary component version string length constexpr uint8_t activeCompVerStrLen = 8; constexpr uint8_t pendingCompVerStrLen = 8; // Arbitrary ActiveVersionStr and pendingVersionStr constexpr char versionsStr[] = {'1', '2', '3', '4', '5', '6', '7', '8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; const struct variable_field versions = { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) .ptr = reinterpret_cast(versionsStr), .length = sizeof(versionsStr)}; struct pldm_downstream_device_parameter_entry_versions entryVersion = {}; entryVersion.entry.active_comp_ver_str_len = activeCompVerStrLen; entryVersion.entry.pending_comp_ver_str_len = pendingCompVerStrLen; int rc = decode_downstream_device_parameter_table_entry_versions( &versions, &entryVersion.entry, entryVersion.active_comp_ver_str, entryVersion.pending_comp_ver_str); EXPECT_EQ(rc, 0); EXPECT_EQ(0, memcmp(entryVersion.active_comp_ver_str, versions.ptr, activeCompVerStrLen)); EXPECT_EQ('\0', entryVersion.active_comp_ver_str[activeCompVerStrLen]); EXPECT_EQ(0, memcmp(entryVersion.pending_comp_ver_str, versions.ptr + activeCompVerStrLen, pendingCompVerStrLen)); EXPECT_EQ('\0', entryVersion.pending_comp_ver_str[activeCompVerStrLen]); EXPECT_EQ(0, memcmp(entryVersion.entry.active_comp_ver_str, versions.ptr, activeCompVerStrLen)); EXPECT_EQ('\0', entryVersion.entry.pending_comp_ver_str[activeCompVerStrLen]); EXPECT_EQ(0, memcmp(entryVersion.entry.pending_comp_ver_str, versions.ptr + activeCompVerStrLen, pendingCompVerStrLen)); EXPECT_EQ('\0', entryVersion.entry.pending_comp_ver_str[activeCompVerStrLen]); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, decodeInvalidDownstreamTableVersions) { // Arbitrary ActiveVersionStr and pendingVersionStr constexpr char versionsStr[] = {'1', '2', '3', '4', '5', '6', '7', '8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; const struct variable_field versions = { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) .ptr = reinterpret_cast(versionsStr), .length = sizeof(versionsStr)}; struct pldm_downstream_device_parameter_entry_versions entryVersion = {}; int rc = decode_downstream_device_parameter_table_entry_versions( &versions, nullptr, entryVersion.active_comp_ver_str, entryVersion.pending_comp_ver_str); EXPECT_EQ(rc, -EINVAL); } #endif #ifdef LIBPLDM_API_TESTING TEST(GetDownstreamFirmwareParameters, decodeOverflowDownstreamTableVersions) { // Arbitrary component version string length constexpr uint8_t activeCompVerStrLen = 8; constexpr uint8_t pendingCompVerStrLen = 8; // Arbitrary ActiveVersionStr and pendingVersionStr constexpr char versionsStr[] = {'1', '2', '3', '4', '5', '6', '7', '8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; const struct variable_field versions = { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) .ptr = reinterpret_cast(versionsStr), .length = sizeof(versionsStr) - 1 // Inject error length }; struct pldm_downstream_device_parameter_entry_versions entryVersion = {}; entryVersion.entry.active_comp_ver_str_len = activeCompVerStrLen; entryVersion.entry.pending_comp_ver_str_len = pendingCompVerStrLen; EXPECT_EQ(decode_downstream_device_parameter_table_entry_versions( &versions, &entryVersion.entry, entryVersion.active_comp_ver_str, entryVersion.pending_comp_ver_str), -EOVERFLOW); } #endif TEST(RequestUpdate, goodPathEncodeRequest) { constexpr uint8_t instanceId = 1; constexpr uint32_t maxTransferSize = 512; constexpr uint16_t numOfComp = 3; constexpr uint8_t maxOutstandingTransferReq = 2; constexpr uint16_t pkgDataLen = 0x1234; constexpr std::string_view compImgSetVerStr = "0penBmcv1.0"; constexpr uint8_t compImgSetVerStrLen = static_cast(compImgSetVerStr.size()); variable_field compImgSetVerStrInfo{}; compImgSetVerStrInfo.ptr = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(compImgSetVerStr.data()); compImgSetVerStrInfo.length = compImgSetVerStrLen; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, requestMsg, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_SUCCESS); std::array outRequest{0x81, 0x05, 0x10, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x02, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65, 0x6e, 0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x30}; EXPECT_EQ(request, outRequest); } TEST(RequestUpdate, errorPathEncodeRequest) { constexpr uint8_t instanceId = 1; uint32_t maxTransferSize = 512; constexpr uint16_t numOfComp = 3; uint8_t maxOutstandingTransferReq = 2; constexpr uint16_t pkgDataLen = 0x1234; constexpr std::string_view compImgSetVerStr = "0penBmcv1.0"; uint8_t compImgSetVerStrLen = static_cast(compImgSetVerStr.size()); variable_field compImgSetVerStrInfo{}; compImgSetVerStrInfo.ptr = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(compImgSetVerStr.data()); compImgSetVerStrInfo.length = compImgSetVerStrLen; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, nullptr, requestMsg, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); compImgSetVerStrInfo.ptr = nullptr; rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, requestMsg, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); compImgSetVerStrInfo.ptr = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(compImgSetVerStr.data()); rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, nullptr, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_request_update_req(instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, requestMsg, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); compImgSetVerStrLen = 0; rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, 0, &compImgSetVerStrInfo, nullptr, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); compImgSetVerStrLen = static_cast(compImgSetVerStr.size()); compImgSetVerStrInfo.length = 0xffff; rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, nullptr, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); compImgSetVerStrInfo.length = compImgSetVerStrLen; maxTransferSize = PLDM_FWUP_BASELINE_TRANSFER_SIZE - 1; rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, nullptr, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); maxTransferSize = PLDM_FWUP_BASELINE_TRANSFER_SIZE; maxOutstandingTransferReq = PLDM_FWUP_MIN_OUTSTANDING_REQ - 1; rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, &compImgSetVerStrInfo, nullptr, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); maxOutstandingTransferReq = PLDM_FWUP_MIN_OUTSTANDING_REQ; rc = encode_request_update_req( instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq, pkgDataLen, PLDM_STR_TYPE_UNKNOWN, compImgSetVerStrLen, &compImgSetVerStrInfo, nullptr, sizeof(struct pldm_request_update_req) + compImgSetVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(RequestUpdate, goodPathDecodeResponse) { constexpr uint16_t fdMetaDataLen = 1024; constexpr uint8_t fdWillSendPkgData = 1; constexpr std::array requestUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(requestUpdateResponse1.data()); uint8_t outCompletionCode = 0; uint16_t outFdMetaDataLen = 0; uint8_t outFdWillSendPkgData = 0; auto rc = decode_request_update_resp( responseMsg1, requestUpdateResponse1.size() - hdrSize, &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outCompletionCode, PLDM_SUCCESS); EXPECT_EQ(outFdMetaDataLen, fdMetaDataLen); EXPECT_EQ(outFdWillSendPkgData, fdWillSendPkgData); outCompletionCode = 0; outFdMetaDataLen = 0; outFdWillSendPkgData = 0; constexpr std::array requestUpdateResponse2{0x00, 0x00, 0x00, 0x81}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(requestUpdateResponse2.data()); rc = decode_request_update_resp( responseMsg2, requestUpdateResponse2.size() - hdrSize, &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outCompletionCode, PLDM_FWUP_ALREADY_IN_UPDATE_MODE); } TEST(RequestUpdate, errorPathDecodeResponse) { constexpr std::array requestUpdateResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x04}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(requestUpdateResponse.data()); uint8_t outCompletionCode = 0; uint16_t outFdMetaDataLen = 0; uint8_t outFdWillSendPkgData = 0; auto rc = decode_request_update_resp( nullptr, requestUpdateResponse.size() - hdrSize, &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_update_resp( responseMsg, requestUpdateResponse.size() - hdrSize, nullptr, &outFdMetaDataLen, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_update_resp( responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode, nullptr, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_update_resp( responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode, &outFdMetaDataLen, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_update_resp(responseMsg, 0, &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_update_resp( responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(PassComponentTable, goodPathEncodeRequest) { constexpr uint8_t instanceId = 1; constexpr uint16_t compIdentifier = 400; constexpr uint8_t compClassificationIndex = 40; constexpr uint32_t compComparisonStamp = 0x12345678; constexpr std::string_view compVerStr = "0penBmcv1.1"; constexpr uint8_t compVerStrLen = static_cast(compVerStr.size()); variable_field compVerStrInfo{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) compVerStrInfo.ptr = reinterpret_cast(compVerStr.data()); compVerStrInfo.length = compVerStrLen; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_SUCCESS); std::array outRequest{0x81, 0x05, 0x13, 0x05, 0x0a, 0x00, 0x90, 0x01, 0x28, 0x78, 0x56, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65, 0x6e, 0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x31}; EXPECT_EQ(request, outRequest); } TEST(PassComponentTable, errorPathEncodeRequest) { constexpr uint8_t instanceId = 1; constexpr uint16_t compIdentifier = 400; constexpr uint8_t compClassificationIndex = 40; constexpr uint32_t compComparisonStamp = 0x12345678; constexpr std::string_view compVerStr = "0penBmcv1.1"; constexpr uint8_t compVerStrLen = static_cast(compVerStr.size()); variable_field compVerStrInfo{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) compVerStrInfo.ptr = reinterpret_cast(compVerStr.data()); compVerStrInfo.length = compVerStrLen; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen, nullptr, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); compVerStrInfo.ptr = nullptr; rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) compVerStrInfo.ptr = reinterpret_cast(compVerStr.data()); rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, nullptr, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req)); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, 0, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen - 1, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END + 1, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_INVALID_TRANSFER_OPERATION_FLAG); rc = encode_pass_component_table_req( instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_UNKNOWN, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_pass_component_table_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(PassComponentTable, goodPathDecodeResponse) { constexpr std::array passCompTableResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse1.data()); uint8_t completionCode = 0; uint8_t compResp = 0; uint8_t compRespCode = 0; auto rc = decode_pass_component_table_resp( responseMsg1, sizeof(pldm_pass_component_table_resp), &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(compResp, PLDM_CR_COMP_CAN_BE_UPDATED); EXPECT_EQ(compRespCode, PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL); constexpr std::array passCompTableResponse2{0x00, 0x00, 0x00, 0x00, 0x00, 0xd0}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse2.data()); rc = decode_pass_component_table_resp( responseMsg2, sizeof(pldm_pass_component_table_resp), &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(compResp, PLDM_CR_COMP_CAN_BE_UPDATED); EXPECT_EQ(compRespCode, PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN); constexpr std::array passCompTableResponse3{0x00, 0x00, 0x00, 0x80}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse3.data()); rc = decode_pass_component_table_resp( responseMsg3, sizeof(pldm_pass_component_table_resp), &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE); } TEST(PassComponentTable, errorPathDecodeResponse) { constexpr std::array passCompTableResponse1{0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse1.data()); uint8_t completionCode = 0; uint8_t compResp = 0; uint8_t compRespCode = 0; auto rc = decode_pass_component_table_resp( nullptr, sizeof(pldm_pass_component_table_resp) - 1, &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pass_component_table_resp( responseMsg1, sizeof(pldm_pass_component_table_resp) - 1, nullptr, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pass_component_table_resp( responseMsg1, sizeof(pldm_pass_component_table_resp) - 1, &completionCode, nullptr, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pass_component_table_resp( responseMsg1, sizeof(pldm_pass_component_table_resp) - 1, &completionCode, &compResp, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pass_component_table_resp(responseMsg1, 0, &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_pass_component_table_resp( responseMsg1, sizeof(pldm_pass_component_table_resp) - 1, &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); constexpr std::array passCompTableResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse2.data()); rc = decode_pass_component_table_resp( responseMsg2, sizeof(pldm_pass_component_table_resp), &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array passCompTableResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse3.data()); rc = decode_pass_component_table_resp( responseMsg3, sizeof(pldm_pass_component_table_resp), &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array passCompTableResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0}; auto responseMsg4 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(passCompTableResponse4.data()); rc = decode_pass_component_table_resp( responseMsg4, sizeof(pldm_pass_component_table_resp), &completionCode, &compResp, &compRespCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(UpdateComponent, goodPathEncodeRequest) { constexpr uint8_t instanceId = 2; constexpr uint16_t compIdentifier = 500; constexpr uint8_t compClassificationIndex = 50; constexpr uint32_t compComparisonStamp = 0x89abcdef; constexpr uint32_t compImageSize = 4096; constexpr bitfield32_t updateOptionFlags{1}; constexpr std::string_view compVerStr = "OpenBmcv2.2"; constexpr uint8_t compVerStrLen = static_cast(compVerStr.size()); variable_field compVerStrInfo{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) compVerStrInfo.ptr = reinterpret_cast(compVerStr.data()); compVerStrInfo.length = compVerStrLen; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_SUCCESS); std::array outRequest{0x82, 0x05, 0x14, 0x0a, 0x00, 0xf4, 0x01, 0x32, 0xef, 0xcd, 0xab, 0x89, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x6d, 0x63, 0x76, 0x32, 0x2e, 0x32}; EXPECT_EQ(request, outRequest); } TEST(UpdateComponent, errorPathEncodeRequest) { constexpr uint8_t instanceId = 2; constexpr uint16_t compIdentifier = 500; constexpr uint8_t compClassificationIndex = 50; constexpr uint32_t compComparisonStamp = 0x89abcdef; constexpr uint32_t compImageSize = 4096; constexpr bitfield32_t updateOptionFlags{1}; constexpr std::string_view compVerStr = "OpenBmcv2.2"; constexpr uint8_t compVerStrLen = static_cast(compVerStr.size()); variable_field compVerStrInfo{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) compVerStrInfo.ptr = reinterpret_cast(compVerStr.data()); compVerStrInfo.length = compVerStrLen; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen, nullptr, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); compVerStrInfo.ptr = nullptr; rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) compVerStrInfo.ptr = reinterpret_cast(compVerStr.data()); rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, nullptr, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req)); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, 0, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, 0, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrLen - 1, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_update_component_req( instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex, compComparisonStamp, compImageSize, updateOptionFlags, PLDM_STR_TYPE_UNKNOWN, compVerStrLen, &compVerStrInfo, requestMsg, sizeof(pldm_update_component_req) + compVerStrLen); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(UpdateComponent, goodPathDecodeResponse) { constexpr std::bitset<32> forceUpdateComp{1}; constexpr uint16_t timeBeforeSendingReqFwData100s = 100; constexpr std::array updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse1.data()); uint8_t completionCode = 0; uint8_t compCompatibilityResp = 0; uint8_t compCompatibilityRespCode = 0; bitfield32_t updateOptionFlagsEnabled{}; uint16_t timeBeforeReqFWData = 0; auto rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp), &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CAN_BE_UPDATED); EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_NO_RESPONSE_CODE); EXPECT_EQ(updateOptionFlagsEnabled.value, forceUpdateComp); EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData100s); constexpr std::bitset<32> noFlags{}; constexpr uint16_t timeBeforeSendingReqFwData0s = 0; constexpr std::array updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse2.data()); rc = decode_update_component_resp( responseMsg2, sizeof(pldm_update_component_resp), &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CANNOT_BE_UPDATED); EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_COMP_INFO_NO_MATCH); EXPECT_EQ(updateOptionFlagsEnabled.value, noFlags); EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData0s); constexpr std::array updateComponentResponse3{0x00, 0x00, 0x00, 0x80}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse3.data()); rc = decode_update_component_resp( responseMsg3, sizeof(pldm_update_component_resp), &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE); } TEST(UpdateComponent, errorPathDecodeResponse) { constexpr std::array updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse1.data()); uint8_t completionCode = 0; uint8_t compCompatibilityResp = 0; uint8_t compCompatibilityRespCode = 0; bitfield32_t updateOptionFlagsEnabled{}; uint16_t timeBeforeReqFWData = 0; auto rc = decode_update_component_resp( nullptr, sizeof(pldm_update_component_resp) - 1, &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp) - 1, nullptr, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode, nullptr, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode, &compCompatibilityResp, nullptr, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, nullptr, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, 0, &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_update_component_resp( responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); constexpr std::array updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse2.data()); rc = decode_update_component_resp( responseMsg2, sizeof(pldm_update_component_resp), &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array updateComponentResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse3.data()); rc = decode_update_component_resp( responseMsg3, sizeof(pldm_update_component_resp), &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array updateComponentResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00}; auto responseMsg4 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(updateComponentResponse4.data()); rc = decode_update_component_resp( responseMsg4, sizeof(pldm_update_component_resp), &completionCode, &compCompatibilityResp, &compCompatibilityRespCode, &updateOptionFlagsEnabled, &timeBeforeReqFWData); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(RequestFirmwareData, goodPathDecodeRequest) { constexpr uint32_t offset = 300; constexpr uint32_t length = 255; constexpr std::array reqFWDataReq{0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(reqFWDataReq.data()); uint32_t outOffset = 0; uint32_t outLength = 0; auto rc = decode_request_firmware_data_req( requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset, &outLength); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outOffset, offset); EXPECT_EQ(outLength, length); } TEST(RequestFirmwareData, errorPathDecodeRequest) { constexpr std::array reqFWDataReq{0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(reqFWDataReq.data()); uint32_t outOffset = 0; uint32_t outLength = 0; auto rc = decode_request_firmware_data_req( nullptr, sizeof(pldm_request_firmware_data_req), &outOffset, &outLength); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_firmware_data_req( requestMsg, sizeof(pldm_request_firmware_data_req), nullptr, &outLength); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_firmware_data_req( requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_request_firmware_data_req( requestMsg, sizeof(pldm_request_firmware_data_req) - 1, &outOffset, &outLength); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = decode_request_firmware_data_req( requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset, &outLength); EXPECT_EQ(rc, PLDM_FWUP_INVALID_TRANSFER_LENGTH); } TEST(RequestFirmwareData, goodPathEncodeResponse) { constexpr uint8_t instanceId = 3; constexpr uint8_t completionCode = PLDM_SUCCESS; constexpr std::array outReqFwDataResponse1{0x03, 0x05, 0x15, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20}; std::array reqFwDataResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto responseMsg1 = reinterpret_cast(reqFwDataResponse1.data()); auto rc = encode_request_firmware_data_resp( instanceId, completionCode, responseMsg1, sizeof(completionCode) + PLDM_FWUP_BASELINE_TRANSFER_SIZE); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(reqFwDataResponse1, outReqFwDataResponse1); constexpr std::array outReqFwDataResponse2{0x03, 0x05, 0x15, 0x82}; std::array reqFwDataResponse2{ 0x00, 0x00, 0x00, 0x00}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto responseMsg2 = reinterpret_cast(reqFwDataResponse2.data()); rc = encode_request_firmware_data_resp( instanceId, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg2, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(reqFwDataResponse2, outReqFwDataResponse2); } TEST(RequestFirmwareData, errorPathEncodeResponse) { std::array reqFwDataResponse{0x00, 0x00, 0x00}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto responseMsg = reinterpret_cast(reqFwDataResponse.data()); auto rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, nullptr, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, responseMsg, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(TransferComplete, goodPathDecodeRequest) { constexpr uint8_t transferResult = PLDM_FWUP_TRANSFER_SUCCESS; constexpr std::array transferCompleteReq1{0x00, 0x00, 0x00, 0x00}; auto requestMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(transferCompleteReq1.data()); uint8_t outTransferResult = 0; auto rc = decode_transfer_complete_req(requestMsg1, sizeof(transferResult), &outTransferResult); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outTransferResult, transferResult); constexpr std::array transferCompleteReq2{0x00, 0x00, 0x00, 0x02}; auto requestMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(transferCompleteReq2.data()); rc = decode_transfer_complete_req(requestMsg2, sizeof(transferResult), &outTransferResult); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outTransferResult, PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT); } TEST(TransferComplete, errorPathDecodeRequest) { constexpr std::array transferCompleteReq{0x00, 0x00, 0x00}; auto requestMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(transferCompleteReq.data()); uint8_t outTransferResult = 0; auto rc = decode_transfer_complete_req(nullptr, 0, &outTransferResult); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_transfer_complete_req(requestMsg, 0, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_transfer_complete_req(requestMsg, 0, &outTransferResult); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(TransferComplete, goodPathEncodeResponse) { constexpr uint8_t instanceId = 4; constexpr uint8_t completionCode = PLDM_SUCCESS; constexpr std::array outTransferCompleteResponse1{0x04, 0x05, 0x16, 0x00}; std::array transferCompleteResponse1{0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(transferCompleteResponse1.data()); auto rc = encode_transfer_complete_resp( instanceId, completionCode, responseMsg1, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(transferCompleteResponse1, outTransferCompleteResponse1); constexpr std::array outTransferCompleteResponse2{0x04, 0x05, 0x16, 0x88}; std::array transferCompleteResponse2{0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(transferCompleteResponse2.data()); rc = encode_transfer_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED, responseMsg2, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(transferCompleteResponse2, outTransferCompleteResponse2); } TEST(TransferComplete, errorPathEncodeResponse) { std::array transferCompleteResponse{0x00, 0x00, 0x00}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(transferCompleteResponse.data()); auto rc = encode_transfer_complete_resp(0, PLDM_SUCCESS, nullptr, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_transfer_complete_resp(0, PLDM_SUCCESS, responseMsg, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(VerifyComplete, goodPathDecodeRequest) { constexpr uint8_t verifyResult = PLDM_FWUP_VERIFY_SUCCESS; constexpr std::array verifyCompleteReq1{0x00, 0x00, 0x00, 0x00}; auto requestMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(verifyCompleteReq1.data()); uint8_t outVerifyResult = 0; auto rc = decode_verify_complete_req(requestMsg1, sizeof(verifyResult), &outVerifyResult); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outVerifyResult, verifyResult); constexpr std::array verifyCompleteReq2{0x00, 0x00, 0x00, 0x03}; auto requestMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(verifyCompleteReq2.data()); rc = decode_verify_complete_req(requestMsg2, sizeof(verifyResult), &outVerifyResult); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outVerifyResult, PLDM_FWUP_VERIFY_FAILED_FD_SECURITY_CHECKS); } TEST(VerifyComplete, errorPathDecodeRequest) { constexpr std::array verifyCompleteReq{0x00, 0x00, 0x00}; auto requestMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(verifyCompleteReq.data()); uint8_t outVerifyResult = 0; auto rc = decode_verify_complete_req(nullptr, 0, &outVerifyResult); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_verify_complete_req(requestMsg, 0, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_verify_complete_req(requestMsg, 0, &outVerifyResult); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(VerifyComplete, goodPathEncodeResponse) { constexpr uint8_t instanceId = 5; constexpr uint8_t completionCode = PLDM_SUCCESS; constexpr std::array outVerifyCompleteResponse1{0x05, 0x05, 0x17, 0x00}; std::array verifyCompleteResponse1{0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(verifyCompleteResponse1.data()); auto rc = encode_verify_complete_resp(instanceId, completionCode, responseMsg1, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(verifyCompleteResponse1, outVerifyCompleteResponse1); constexpr std::array outVerifyCompleteResponse2{0x05, 0x05, 0x17, 0x88}; std::array verifyCompleteResponse2{0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(verifyCompleteResponse2.data()); rc = encode_verify_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED, responseMsg2, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(verifyCompleteResponse2, outVerifyCompleteResponse2); } TEST(VerifyComplete, errorPathEncodeResponse) { std::array verifyCompleteResponse{0x00, 0x00, 0x00}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(verifyCompleteResponse.data()); auto rc = encode_verify_complete_resp(0, PLDM_SUCCESS, nullptr, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_verify_complete_resp(0, PLDM_SUCCESS, responseMsg, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(ApplyComplete, goodPathDecodeRequest) { constexpr uint8_t applyResult1 = PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD; // DC power cycle [Bit position 4] & AC power cycle [Bit position 5] constexpr std::bitset<16> compActivationModification1{0x30}; constexpr std::array applyCompleteReq1{0x00, 0x00, 0x00, 0x01, 0x30, 0x00}; auto requestMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteReq1.data()); uint8_t outApplyResult = 0; bitfield16_t outCompActivationModification{}; auto rc = decode_apply_complete_req( requestMsg1, sizeof(pldm_apply_complete_req), &outApplyResult, &outCompActivationModification); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outApplyResult, applyResult1); EXPECT_EQ(outCompActivationModification.value, compActivationModification1); constexpr uint8_t applyResult2 = PLDM_FWUP_APPLY_SUCCESS; constexpr std::bitset<16> compActivationModification2{}; constexpr std::array applyCompleteReq2{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto requestMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteReq2.data()); rc = decode_apply_complete_req(requestMsg2, sizeof(pldm_apply_complete_req), &outApplyResult, &outCompActivationModification); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(outApplyResult, applyResult2); EXPECT_EQ(outCompActivationModification.value, compActivationModification2); } TEST(ApplyComplete, errorPathDecodeRequest) { constexpr std::array applyCompleteReq1{0x00, 0x00, 0x00}; auto requestMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteReq1.data()); uint8_t outApplyResult = 0; bitfield16_t outCompActivationModification{}; auto rc = decode_apply_complete_req( nullptr, sizeof(pldm_apply_complete_req), &outApplyResult, &outCompActivationModification); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_apply_complete_req(requestMsg1, sizeof(pldm_apply_complete_req), nullptr, &outCompActivationModification); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_apply_complete_req(requestMsg1, sizeof(pldm_apply_complete_req), &outApplyResult, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_apply_complete_req(requestMsg1, 0, &outApplyResult, &outCompActivationModification); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); constexpr std::array applyCompleteReq2{0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; auto requestMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteReq2.data()); rc = decode_apply_complete_req(requestMsg2, sizeof(pldm_apply_complete_req), &outApplyResult, &outCompActivationModification); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(ApplyComplete, goodPathEncodeResponse) { constexpr uint8_t instanceId = 6; constexpr uint8_t completionCode = PLDM_SUCCESS; constexpr std::array outApplyCompleteResponse1{0x06, 0x05, 0x18, 0x00}; std::array applyCompleteResponse1{0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteResponse1.data()); auto rc = encode_apply_complete_resp(instanceId, completionCode, responseMsg1, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(applyCompleteResponse1, outApplyCompleteResponse1); constexpr std::array outApplyCompleteResponse2{0x06, 0x05, 0x18, 0x88}; std::array applyCompleteResponse2{0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteResponse2.data()); rc = encode_apply_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED, responseMsg2, sizeof(completionCode)); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(applyCompleteResponse2, outApplyCompleteResponse2); } TEST(ApplyComplete, errorPathEncodeResponse) { std::array applyCompleteResponse{0x00, 0x00, 0x00}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(applyCompleteResponse.data()); auto rc = encode_apply_complete_resp(0, PLDM_SUCCESS, nullptr, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_apply_complete_resp(0, PLDM_SUCCESS, responseMsg, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(ActivateFirmware, goodPathEncodeRequest) { constexpr uint8_t instanceId = 7; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_activate_firmware_req( instanceId, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg, sizeof(pldm_activate_firmware_req)); EXPECT_EQ(rc, PLDM_SUCCESS); std::array outRequest{0x87, 0x05, 0x1a, 0x01}; EXPECT_EQ(request, outRequest); } TEST(ActivateFirmware, errorPathEncodeRequest) { std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_activate_firmware_req( 0, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, nullptr, sizeof(pldm_activate_firmware_req)); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_activate_firmware_req( 0, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg, 0); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); rc = encode_activate_firmware_req(0, 2, requestMsg, sizeof(pldm_activate_firmware_req)); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(ActivateFirmware, goodPathDecodeResponse) { constexpr uint16_t estimatedTimeForActivation100s = 100; constexpr std::array activateFirmwareResponse1{0x00, 0x00, 0x00, 0x00, 0x64, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(activateFirmwareResponse1.data()); uint8_t completionCode = 0; uint16_t estimatedTimeForActivation = 0; auto rc = decode_activate_firmware_resp( responseMsg1, sizeof(pldm_activate_firmware_resp), &completionCode, &estimatedTimeForActivation); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(estimatedTimeForActivation, estimatedTimeForActivation100s); constexpr std::array activateFirmwareResponse2{0x00, 0x00, 0x00, 0x85}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(activateFirmwareResponse2.data()); rc = decode_activate_firmware_resp(responseMsg2, sizeof(completionCode), &completionCode, &estimatedTimeForActivation); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_FWUP_INCOMPLETE_UPDATE); } TEST(ActivateFirmware, errorPathDecodeResponse) { constexpr std::array activateFirmwareResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(activateFirmwareResponse.data()); uint8_t completionCode = 0; uint16_t estimatedTimeForActivation = 0; auto rc = decode_activate_firmware_resp( nullptr, sizeof(pldm_activate_firmware_resp), &completionCode, &estimatedTimeForActivation); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_activate_firmware_resp(responseMsg, sizeof(pldm_activate_firmware_resp), nullptr, &estimatedTimeForActivation); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_activate_firmware_resp(responseMsg, sizeof(pldm_activate_firmware_resp), &completionCode, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_activate_firmware_resp(responseMsg, 0, &completionCode, &estimatedTimeForActivation); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_activate_firmware_resp( responseMsg, sizeof(pldm_activate_firmware_resp) - 1, &completionCode, &estimatedTimeForActivation); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(GetStatus, goodPathEncodeRequest) { constexpr uint8_t instanceId = 8; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_get_status_req(instanceId, requestMsg, PLDM_GET_STATUS_REQ_BYTES); EXPECT_EQ(rc, PLDM_SUCCESS); constexpr std::array outRequest{0x88, 0x05, 0x1b}; EXPECT_EQ(request, outRequest); } TEST(GetStatus, errorPathEncodeRequest) { std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_get_status_req(0, nullptr, PLDM_GET_STATUS_REQ_BYTES); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_get_status_req(0, requestMsg, PLDM_GET_STATUS_REQ_BYTES + 1); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(GetStatus, goodPathDecodeResponse) { constexpr std::bitset<32> updateOptionFlagsEnabled1{0}; constexpr std::array getStatusResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x09, 0x65, 0x05, 0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse1.data()); uint8_t completionCode = 0; uint8_t currentState = 0; uint8_t previousState = 0; uint8_t auxState = 0; uint8_t auxStateStatus = 0; uint8_t progressPercent = 0; uint8_t reasonCode = 0; bitfield32_t updateOptionFlagsEnabled{0}; auto rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(currentState, PLDM_FD_STATE_IDLE); EXPECT_EQ(previousState, PLDM_FD_STATE_DOWNLOAD); EXPECT_EQ(auxState, PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER); EXPECT_EQ(auxStateStatus, PLDM_FD_TIMEOUT); EXPECT_EQ(progressPercent, PLDM_FWUP_MAX_PROGRESS_PERCENT); EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD); EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled1); // Bit position 0 - Force update of component – FD will perform a force // update of the component. constexpr std::bitset<32> updateOptionFlagsEnabled2{1}; constexpr uint8_t progressPercent2 = 50; constexpr std::array getStatusResponse2{0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x70, 0x32, 0x05, 0x01, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse2.data()); rc = decode_get_status_resp( responseMsg2, getStatusResponse2.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(currentState, PLDM_FD_STATE_VERIFY); EXPECT_EQ(previousState, PLDM_FD_STATE_DOWNLOAD); EXPECT_EQ(auxState, PLDM_FD_OPERATION_IN_PROGRESS); EXPECT_EQ(auxStateStatus, PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START); EXPECT_EQ(progressPercent, progressPercent2); EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD); EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled2); constexpr std::array getStatusResponse3{0x00, 0x00, 0x00, 0x04}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse3.data()); rc = decode_get_status_resp( responseMsg3, getStatusResponse3.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_ERROR_NOT_READY); } TEST(GetStatus, errorPathDecodeResponse) { uint8_t completionCode = 0; uint8_t currentState = 0; uint8_t previousState = 0; uint8_t auxState = 0; uint8_t auxStateStatus = 0; uint8_t progressPercent = 0; uint8_t reasonCode = 0; bitfield32_t updateOptionFlagsEnabled{0}; constexpr std::array getStatusResponse1{0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse1.data()); auto rc = decode_get_status_resp( nullptr, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, nullptr, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, nullptr, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, nullptr, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, nullptr, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, nullptr, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, nullptr, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, nullptr, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_get_status_resp( responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array getStatusResponse2{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse2.data()); rc = decode_get_status_resp( responseMsg2, getStatusResponse2.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); constexpr std::array getStatusResponse3{0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse3.data()); rc = decode_get_status_resp( responseMsg3, getStatusResponse3.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array getStatusResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg4 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse4.data()); rc = decode_get_status_resp( responseMsg4, getStatusResponse4.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array getStatusResponse5{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg5 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse5.data()); rc = decode_get_status_resp( responseMsg5, getStatusResponse5.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array getStatusResponse6{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg6 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse6.data()); rc = decode_get_status_resp( responseMsg6, getStatusResponse6.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array getStatusResponse7{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg7 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse7.data()); rc = decode_get_status_resp( responseMsg7, getStatusResponse7.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array getStatusResponse8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00}; auto responseMsg8 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse8.data()); rc = decode_get_status_resp( responseMsg8, getStatusResponse8.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); // AuxState is not PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER when the state is // IDLE constexpr std::array getStatusResponse9{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg9 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(getStatusResponse9.data()); rc = decode_get_status_resp( responseMsg9, getStatusResponse9.size() - hdrSize, &completionCode, ¤tState, &previousState, &auxState, &auxStateStatus, &progressPercent, &reasonCode, &updateOptionFlagsEnabled); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); } TEST(CancelUpdateComponent, goodPathEncodeRequest) { constexpr uint8_t instanceId = 9; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_cancel_update_component_req( instanceId, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES); EXPECT_EQ(rc, PLDM_SUCCESS); constexpr std::array outRequest{0x89, 0x05, 0x1c}; EXPECT_EQ(request, outRequest); } TEST(CancelUpdateComponent, errorPathEncodeRequest) { std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_cancel_update_component_req( 0, nullptr, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_cancel_update_component_req( 0, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES + 1); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(CancelUpdateComponent, testGoodDecodeResponse) { uint8_t completionCode = 0; constexpr std::array cancelUpdateComponentResponse1{0x00, 0x00, 0x00, 0x00}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto responseMsg1 = reinterpret_cast( cancelUpdateComponentResponse1.data()); auto rc = decode_cancel_update_component_resp( responseMsg1, cancelUpdateComponentResponse1.size() - hdrSize, &completionCode); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); constexpr std::array cancelUpdateComponentResponse2{0x00, 0x00, 0x00, 0x86}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto responseMsg2 = reinterpret_cast( cancelUpdateComponentResponse2.data()); rc = decode_cancel_update_component_resp( responseMsg2, cancelUpdateComponentResponse2.size() - hdrSize, &completionCode); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_FWUP_BUSY_IN_BACKGROUND); } TEST(CancelUpdateComponent, testBadDecodeResponse) { uint8_t completionCode = 0; constexpr std::array cancelUpdateComponentResponse{ 0x00, 0x00, 0x00}; auto responseMsg = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateComponentResponse.data()); auto rc = decode_cancel_update_component_resp( nullptr, cancelUpdateComponentResponse.size() - hdrSize, &completionCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_cancel_update_component_resp( responseMsg, cancelUpdateComponentResponse.size() - hdrSize, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_cancel_update_component_resp( responseMsg, cancelUpdateComponentResponse.size() - hdrSize, &completionCode); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(CancelUpdate, goodPathEncodeRequest) { constexpr uint8_t instanceId = 10; std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_cancel_update_req(instanceId, requestMsg, PLDM_CANCEL_UPDATE_REQ_BYTES); EXPECT_EQ(rc, PLDM_SUCCESS); constexpr std::array outRequest{0x8a, 0x05, 0x1d}; EXPECT_EQ(request, outRequest); } TEST(CancelUpdate, errorPathEncodeRequest) { std::array request{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto requestMsg = reinterpret_cast(request.data()); auto rc = encode_cancel_update_req(0, nullptr, PLDM_CANCEL_UPDATE_REQ_BYTES); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = encode_cancel_update_req(0, requestMsg, PLDM_CANCEL_UPDATE_REQ_BYTES + 1); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); } TEST(CancelUpdate, goodPathDecodeResponse) { constexpr std::bitset<64> nonFunctioningComponentBitmap1{0}; constexpr std::array cancelUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateResponse1.data()); uint8_t completionCode = 0; bool8_t nonFunctioningComponentIndication = 0; bitfield64_t nonFunctioningComponentBitmap{0}; auto rc = decode_cancel_update_resp( responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(nonFunctioningComponentIndication, PLDM_FWUP_COMPONENTS_FUNCTIONING); EXPECT_EQ(nonFunctioningComponentBitmap.value, nonFunctioningComponentBitmap1); constexpr std::bitset<64> nonFunctioningComponentBitmap2{0x0101}; constexpr std::array cancelUpdateResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateResponse2.data()); rc = decode_cancel_update_resp( responseMsg2, cancelUpdateResponse2.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_SUCCESS); EXPECT_EQ(nonFunctioningComponentIndication, PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING); EXPECT_EQ(nonFunctioningComponentBitmap.value, nonFunctioningComponentBitmap2); constexpr std::array cancelUpdateResponse3{0x00, 0x00, 0x00, 0x86}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateResponse3.data()); rc = decode_cancel_update_resp( responseMsg3, cancelUpdateResponse3.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_SUCCESS); EXPECT_EQ(completionCode, PLDM_FWUP_BUSY_IN_BACKGROUND); } TEST(CancelUpdate, errorPathDecodeResponse) { constexpr std::array cancelUpdateResponse1{0x00, 0x00, 0x00}; auto responseMsg1 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateResponse1.data()); uint8_t completionCode = 0; bool8_t nonFunctioningComponentIndication = 0; bitfield64_t nonFunctioningComponentBitmap{0}; auto rc = decode_cancel_update_resp( nullptr, cancelUpdateResponse1.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_cancel_update_resp( responseMsg1, cancelUpdateResponse1.size() - hdrSize, nullptr, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_cancel_update_resp( responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode, nullptr, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_cancel_update_resp( responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, nullptr); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); rc = decode_cancel_update_resp( responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); constexpr std::array cancelUpdateResponse2{0x00, 0x00, 0x00, 0x00}; auto responseMsg2 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateResponse2.data()); rc = decode_cancel_update_resp( responseMsg2, cancelUpdateResponse2.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH); constexpr std::array cancelUpdateResponse3{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; auto responseMsg3 = // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast(cancelUpdateResponse3.data()); rc = decode_cancel_update_resp( responseMsg3, cancelUpdateResponse3.size() - hdrSize, &completionCode, &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap); EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA); }