Move libpldm test cases into libpldm directory
The test cases for different libraries in this repo are put in the same
test directory.
As a follow up of building libpldm only, move the test cases of libpldm
into libpldm/tests, so that the test cases could be built and run by
libpldm-only option.
Tested: Verify the libpldm tests are built and run by libpldm-only
option.
Verify all the tests are built and run without libpldm-only
option.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I097000bef316f787ef1894f1a3feec5089ea081a
diff --git a/libpldm/meson.build b/libpldm/meson.build
index 9d24b2c..bd10096 100644
--- a/libpldm/meson.build
+++ b/libpldm/meson.build
@@ -62,3 +62,7 @@
description: 'PLDM protocol encode/decode C lib',
version: meson.project_version(),
libraries: libpldm)
+
+if get_option('tests').enabled()
+ subdir('tests')
+endif
diff --git a/libpldm/tests/.clang-format b/libpldm/tests/.clang-format
new file mode 100644
index 0000000..ae9ad39
--- /dev/null
+++ b/libpldm/tests/.clang-format
@@ -0,0 +1,98 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
diff --git a/libpldm/tests/libpldm_base_test.cpp b/libpldm/tests/libpldm_base_test.cpp
new file mode 100644
index 0000000..b8b25d3
--- /dev/null
+++ b/libpldm/tests/libpldm_base_test.cpp
@@ -0,0 +1,545 @@
+#include <string.h>
+
+#include <array>
+#include <cstring>
+#include <vector>
+
+#include "libpldm/base.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using testing::ElementsAreArray;
+
+constexpr auto hdrSize = sizeof(pldm_msg_hdr);
+
+TEST(PackPLDMMessage, BadPathTest)
+{
+ struct pldm_header_info hdr;
+ struct pldm_header_info* hdr_ptr = NULL;
+ pldm_msg_hdr msg{};
+
+ // PLDM header information pointer is NULL
+ auto rc = pack_pldm_header(hdr_ptr, &msg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // PLDM message pointer is NULL
+ rc = pack_pldm_header(&hdr, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // PLDM header information pointer and PLDM message pointer is NULL
+ rc = pack_pldm_header(hdr_ptr, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // RESERVED message type
+ hdr.msg_type = PLDM_RESERVED;
+ rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // Instance ID out of range
+ hdr.msg_type = PLDM_REQUEST;
+ hdr.instance = 32;
+ rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // PLDM type out of range
+ hdr.msg_type = PLDM_REQUEST;
+ hdr.instance = 31;
+ hdr.pldm_type = 64;
+ rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_PLDM_TYPE);
+}
+
+TEST(PackPLDMMessage, RequestMessageGoodPath)
+{
+ struct pldm_header_info hdr;
+ pldm_msg_hdr msg{};
+
+ // Message type is REQUEST and lower range of the field values
+ hdr.msg_type = PLDM_REQUEST;
+ hdr.instance = 0;
+ hdr.pldm_type = 0;
+ hdr.command = 0;
+
+ auto rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(msg.request, 1);
+ EXPECT_EQ(msg.datagram, 0);
+ EXPECT_EQ(msg.instance_id, 0);
+ EXPECT_EQ(msg.type, 0);
+ EXPECT_EQ(msg.command, 0);
+
+ // Message type is REQUEST and upper range of the field values
+ hdr.instance = 31;
+ hdr.pldm_type = 63;
+ hdr.command = 255;
+
+ rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(msg.request, 1);
+ EXPECT_EQ(msg.datagram, 0);
+ EXPECT_EQ(msg.instance_id, 31);
+ EXPECT_EQ(msg.type, 63);
+ EXPECT_EQ(msg.command, 255);
+
+ // Message type is PLDM_ASYNC_REQUEST_NOTIFY
+ hdr.msg_type = PLDM_ASYNC_REQUEST_NOTIFY;
+
+ rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(msg.request, 1);
+ EXPECT_EQ(msg.datagram, 1);
+ EXPECT_EQ(msg.instance_id, 31);
+ EXPECT_EQ(msg.type, 63);
+ EXPECT_EQ(msg.command, 255);
+}
+
+TEST(PackPLDMMessage, ResponseMessageGoodPath)
+{
+ struct pldm_header_info hdr;
+ pldm_msg_hdr msg{};
+
+ // Message type is PLDM_RESPONSE and lower range of the field values
+ hdr.msg_type = PLDM_RESPONSE;
+ hdr.instance = 0;
+ hdr.pldm_type = 0;
+ hdr.command = 0;
+
+ auto rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(msg.request, 0);
+ EXPECT_EQ(msg.datagram, 0);
+ EXPECT_EQ(msg.instance_id, 0);
+ EXPECT_EQ(msg.type, 0);
+ EXPECT_EQ(msg.command, 0);
+
+ // Message type is PLDM_RESPONSE and upper range of the field values
+ hdr.instance = 31;
+ hdr.pldm_type = 63;
+ hdr.command = 255;
+
+ rc = pack_pldm_header(&hdr, &msg);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(msg.request, 0);
+ EXPECT_EQ(msg.datagram, 0);
+ EXPECT_EQ(msg.instance_id, 31);
+ EXPECT_EQ(msg.type, 63);
+ EXPECT_EQ(msg.command, 255);
+}
+
+TEST(UnpackPLDMMessage, BadPathTest)
+{
+ struct pldm_header_info hdr;
+
+ // PLDM message pointer is NULL
+ auto rc = unpack_pldm_header(nullptr, &hdr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(UnpackPLDMMessage, RequestMessageGoodPath)
+{
+ struct pldm_header_info hdr;
+ pldm_msg_hdr msg{};
+
+ // Unpack PLDM request message and lower range of field values
+ msg.request = 1;
+ auto rc = unpack_pldm_header(&msg, &hdr);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(hdr.msg_type, PLDM_REQUEST);
+ EXPECT_EQ(hdr.instance, 0);
+ EXPECT_EQ(hdr.pldm_type, 0);
+ EXPECT_EQ(hdr.command, 0);
+
+ // Unpack PLDM async request message and lower range of field values
+ msg.datagram = 1;
+ rc = unpack_pldm_header(&msg, &hdr);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(hdr.msg_type, PLDM_ASYNC_REQUEST_NOTIFY);
+
+ // Unpack PLDM request message and upper range of field values
+ msg.datagram = 0;
+ msg.instance_id = 31;
+ msg.type = 63;
+ msg.command = 255;
+ rc = unpack_pldm_header(&msg, &hdr);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(hdr.msg_type, PLDM_REQUEST);
+ EXPECT_EQ(hdr.instance, 31);
+ EXPECT_EQ(hdr.pldm_type, 63);
+ EXPECT_EQ(hdr.command, 255);
+}
+
+TEST(UnpackPLDMMessage, ResponseMessageGoodPath)
+{
+ struct pldm_header_info hdr;
+ pldm_msg_hdr msg{};
+
+ // Unpack PLDM response message and lower range of field values
+ auto rc = unpack_pldm_header(&msg, &hdr);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(hdr.msg_type, PLDM_RESPONSE);
+ EXPECT_EQ(hdr.instance, 0);
+ EXPECT_EQ(hdr.pldm_type, 0);
+ EXPECT_EQ(hdr.command, 0);
+
+ // Unpack PLDM response message and upper range of field values
+ msg.instance_id = 31;
+ msg.type = 63;
+ msg.command = 255;
+ rc = unpack_pldm_header(&msg, &hdr);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(hdr.msg_type, PLDM_RESPONSE);
+ EXPECT_EQ(hdr.instance, 31);
+ EXPECT_EQ(hdr.pldm_type, 63);
+ EXPECT_EQ(hdr.command, 255);
+}
+
+TEST(GetPLDMCommands, testEncodeRequest)
+{
+ uint8_t pldmType = 0x05;
+ ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_commands_req(0, pldmType, version, request);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(0, memcmp(request->payload, &pldmType, sizeof(pldmType)));
+ EXPECT_EQ(0, memcmp(request->payload + sizeof(pldmType), &version,
+ sizeof(version)));
+}
+
+TEST(GetPLDMCommands, testDecodeRequest)
+{
+ uint8_t pldmType = 0x05;
+ ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
+ uint8_t pldmTypeOut{};
+ ver32_t versionOut{0xFF, 0xFF, 0xFF, 0xFF};
+ std::array<uint8_t, hdrSize + PLDM_GET_COMMANDS_REQ_BYTES> requestMsg{};
+
+ memcpy(requestMsg.data() + hdrSize, &pldmType, sizeof(pldmType));
+ memcpy(requestMsg.data() + sizeof(pldmType) + hdrSize, &version,
+ sizeof(version));
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = decode_get_commands_req(request, requestMsg.size() - hdrSize,
+ &pldmTypeOut, &versionOut);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(pldmTypeOut, pldmType);
+ EXPECT_EQ(0, memcmp(&versionOut, &version, sizeof(version)));
+}
+
+TEST(GetPLDMCommands, testEncodeResponse)
+{
+ uint8_t completionCode = 0;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_RESP_BYTES>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> commands{};
+ commands[0].byte = 1;
+ commands[1].byte = 2;
+ commands[2].byte = 3;
+
+ auto rc =
+ encode_get_commands_resp(0, PLDM_SUCCESS, commands.data(), response);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ uint8_t* payload_ptr = response->payload;
+ EXPECT_EQ(completionCode, payload_ptr[0]);
+ EXPECT_EQ(1, payload_ptr[sizeof(completionCode)]);
+ EXPECT_EQ(2,
+ payload_ptr[sizeof(completionCode) + sizeof(commands[0].byte)]);
+ EXPECT_EQ(3, payload_ptr[sizeof(completionCode) + sizeof(commands[0].byte) +
+ sizeof(commands[1].byte)]);
+}
+
+TEST(GetPLDMTypes, testEncodeResponse)
+{
+ uint8_t completionCode = 0;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_TYPES_RESP_BYTES>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ std::array<bitfield8_t, PLDM_MAX_TYPES / 8> types{};
+ types[0].byte = 1;
+ types[1].byte = 2;
+ types[2].byte = 3;
+
+ auto rc = encode_get_types_resp(0, PLDM_SUCCESS, types.data(), response);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ uint8_t* payload_ptr = response->payload;
+ EXPECT_EQ(completionCode, payload_ptr[0]);
+ EXPECT_EQ(1, payload_ptr[sizeof(completionCode)]);
+ EXPECT_EQ(2, payload_ptr[sizeof(completionCode) + sizeof(types[0].byte)]);
+ EXPECT_EQ(3, payload_ptr[sizeof(completionCode) + sizeof(types[0].byte) +
+ sizeof(types[1].byte)]);
+}
+
+TEST(GetPLDMTypes, testGoodDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
+ responseMsg[1 + hdrSize] = 1;
+ responseMsg[2 + hdrSize] = 2;
+ responseMsg[3 + hdrSize] = 3;
+ std::array<bitfield8_t, PLDM_MAX_TYPES / 8> outTypes{};
+
+ uint8_t completion_code;
+ responseMsg[hdrSize] = PLDM_SUCCESS;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_types_resp(response, responseMsg.size() - hdrSize,
+ &completion_code, outTypes.data());
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completion_code, PLDM_SUCCESS);
+ EXPECT_EQ(responseMsg[1 + hdrSize], outTypes[0].byte);
+ EXPECT_EQ(responseMsg[2 + hdrSize], outTypes[1].byte);
+ EXPECT_EQ(responseMsg[3 + hdrSize], outTypes[2].byte);
+}
+
+TEST(GetPLDMTypes, testBadDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
+ responseMsg[1 + hdrSize] = 1;
+ responseMsg[2 + hdrSize] = 2;
+ responseMsg[3 + hdrSize] = 3;
+ std::array<bitfield8_t, PLDM_MAX_TYPES / 8> outTypes{};
+
+ uint8_t retcompletion_code = 0;
+ responseMsg[hdrSize] = PLDM_SUCCESS;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_types_resp(response, responseMsg.size() - hdrSize - 1,
+ &retcompletion_code, outTypes.data());
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetPLDMCommands, testGoodDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
+ responseMsg[1 + hdrSize] = 1;
+ responseMsg[2 + hdrSize] = 2;
+ responseMsg[3 + hdrSize] = 3;
+ std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> outTypes{};
+
+ uint8_t completion_code;
+ responseMsg[hdrSize] = PLDM_SUCCESS;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_commands_resp(response, responseMsg.size() - hdrSize,
+ &completion_code, outTypes.data());
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completion_code, PLDM_SUCCESS);
+ EXPECT_EQ(responseMsg[1 + hdrSize], outTypes[0].byte);
+ EXPECT_EQ(responseMsg[2 + hdrSize], outTypes[1].byte);
+ EXPECT_EQ(responseMsg[3 + hdrSize], outTypes[2].byte);
+}
+
+TEST(GetPLDMCommands, testBadDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
+ responseMsg[1 + hdrSize] = 1;
+ responseMsg[2 + hdrSize] = 2;
+ responseMsg[3 + hdrSize] = 3;
+ std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> outTypes{};
+
+ uint8_t retcompletion_code = 0;
+ responseMsg[hdrSize] = PLDM_SUCCESS;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc =
+ decode_get_commands_resp(response, responseMsg.size() - hdrSize - 1,
+ &retcompletion_code, outTypes.data());
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetPLDMVersion, testGoodEncodeRequest)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ uint8_t pldmType = 0x03;
+ uint32_t transferHandle = 0x0;
+ uint8_t opFlag = 0x01;
+
+ auto rc =
+ encode_get_version_req(0, transferHandle, opFlag, pldmType, request);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(
+ 0, memcmp(request->payload, &transferHandle, sizeof(transferHandle)));
+ EXPECT_EQ(0, memcmp(request->payload + sizeof(transferHandle), &opFlag,
+ sizeof(opFlag)));
+ EXPECT_EQ(0,
+ memcmp(request->payload + sizeof(transferHandle) + sizeof(opFlag),
+ &pldmType, sizeof(pldmType)));
+}
+
+TEST(GetPLDMVersion, testBadEncodeRequest)
+{
+ uint8_t pldmType = 0x03;
+ uint32_t transferHandle = 0x0;
+ uint8_t opFlag = 0x01;
+
+ auto rc =
+ encode_get_version_req(0, transferHandle, opFlag, pldmType, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetPLDMVersion, testEncodeResponse)
+{
+ uint8_t completionCode = 0;
+ uint32_t transferHandle = 0;
+ uint8_t flag = PLDM_START_AND_END;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ ver32_t version = {0xFF, 0xFF, 0xFF, 0xFF};
+
+ auto rc = encode_get_version_resp(0, PLDM_SUCCESS, 0, PLDM_START_AND_END,
+ &version, sizeof(ver32_t), response);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, response->payload[0]);
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]),
+ &transferHandle, sizeof(transferHandle)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(transferHandle),
+ &flag, sizeof(flag)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(transferHandle) + sizeof(flag),
+ &version, sizeof(version)));
+}
+
+TEST(GetPLDMVersion, testDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_VERSION_REQ_BYTES> requestMsg{};
+ uint32_t transferHandle = 0x0;
+ uint32_t retTransferHandle = 0x0;
+ uint8_t flag = PLDM_GET_FIRSTPART;
+ uint8_t retFlag = PLDM_GET_FIRSTPART;
+ uint8_t pldmType = PLDM_BASE;
+ uint8_t retType = PLDM_BASE;
+
+ memcpy(requestMsg.data() + hdrSize, &transferHandle,
+ sizeof(transferHandle));
+ memcpy(requestMsg.data() + sizeof(transferHandle) + hdrSize, &flag,
+ sizeof(flag));
+ memcpy(requestMsg.data() + sizeof(transferHandle) + sizeof(flag) + hdrSize,
+ &pldmType, sizeof(pldmType));
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = decode_get_version_req(request, requestMsg.size() - hdrSize,
+ &retTransferHandle, &retFlag, &retType);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(transferHandle, retTransferHandle);
+ EXPECT_EQ(flag, retFlag);
+ EXPECT_EQ(pldmType, retType);
+}
+
+TEST(GetPLDMVersion, testDecodeResponse)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES>
+ responseMsg{};
+ uint32_t transferHandle = 0x0;
+ uint32_t retTransferHandle = 0x0;
+ uint8_t flag = PLDM_START_AND_END;
+ uint8_t retFlag = PLDM_START_AND_END;
+ uint8_t completionCode = 0;
+ ver32_t version = {0xFF, 0xFF, 0xFF, 0xFF};
+ ver32_t versionOut;
+ uint8_t completion_code;
+
+ memcpy(responseMsg.data() + sizeof(completionCode) + hdrSize,
+ &transferHandle, sizeof(transferHandle));
+ memcpy(responseMsg.data() + sizeof(completionCode) +
+ sizeof(transferHandle) + hdrSize,
+ &flag, sizeof(flag));
+ memcpy(responseMsg.data() + sizeof(completionCode) +
+ sizeof(transferHandle) + sizeof(flag) + hdrSize,
+ &version, sizeof(version));
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_version_resp(response, responseMsg.size() - hdrSize,
+ &completion_code, &retTransferHandle,
+ &retFlag, &versionOut);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(transferHandle, retTransferHandle);
+ EXPECT_EQ(flag, retFlag);
+
+ EXPECT_EQ(versionOut.major, version.major);
+ EXPECT_EQ(versionOut.minor, version.minor);
+ EXPECT_EQ(versionOut.update, version.update);
+ EXPECT_EQ(versionOut.alpha, version.alpha);
+}
+
+TEST(GetTID, testEncodeRequest)
+{
+ pldm_msg request{};
+
+ auto rc = encode_get_tid_req(0, &request);
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+}
+
+TEST(GetTID, testEncodeResponse)
+{
+ uint8_t completionCode = 0;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_TID_RESP_BYTES>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ uint8_t tid = 1;
+
+ auto rc = encode_get_tid_resp(0, PLDM_SUCCESS, tid, response);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ uint8_t* payload = response->payload;
+ EXPECT_EQ(completionCode, payload[0]);
+ EXPECT_EQ(1, payload[sizeof(completionCode)]);
+}
+
+TEST(GetTID, testDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_TID_RESP_BYTES> responseMsg{};
+ responseMsg[1 + hdrSize] = 1;
+
+ uint8_t tid;
+ uint8_t completion_code;
+ responseMsg[hdrSize] = PLDM_SUCCESS;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_tid_resp(response, responseMsg.size() - hdrSize,
+ &completion_code, &tid);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completion_code, PLDM_SUCCESS);
+ EXPECT_EQ(tid, 1);
+}
+
+TEST(CcOnlyResponse, testEncode)
+{
+ struct pldm_msg responseMsg;
+
+ auto rc =
+ encode_cc_only_resp(0 /*instance id*/, 1 /*pldm type*/, 2 /*command*/,
+ 3 /*complection code*/, &responseMsg);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ auto p = reinterpret_cast<uint8_t*>(&responseMsg);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + sizeof(responseMsg)),
+ ElementsAreArray({0, 1, 2, 3}));
+
+ rc = encode_cc_only_resp(PLDM_INSTANCE_MAX + 1, 1, 2, 3, &responseMsg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = encode_cc_only_resp(0, 1, 2, 3, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
diff --git a/libpldm/tests/libpldm_bios_table_test.cpp b/libpldm/tests/libpldm_bios_table_test.cpp
new file mode 100644
index 0000000..b4a6022
--- /dev/null
+++ b/libpldm/tests/libpldm_bios_table_test.cpp
@@ -0,0 +1,1111 @@
+#include <endian.h>
+#include <string.h>
+
+#include <cstring>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "libpldm/base.h"
+#include "libpldm/bios.h"
+#include "libpldm/bios_table.h"
+#include "libpldm/utils.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using testing::ElementsAreArray;
+using Table = std::vector<uint8_t>;
+
+void buildTable(Table& table)
+{
+ auto padSize = ((table.size() % 4) ? (4 - table.size() % 4) : 0);
+ table.insert(table.end(), padSize, 0);
+ uint32_t checksum = crc32(table.data(), table.size());
+ checksum = htole32(checksum);
+ uint8_t a[4];
+ std::memcpy(a, &checksum, sizeof(checksum));
+ table.insert(table.end(), std::begin(a), std::end(a));
+}
+
+template <typename First, typename... Rest>
+void buildTable(Table& table, First& first, Rest&... rest)
+{
+ table.insert(table.end(), first.begin(), first.end());
+ buildTable(table, rest...);
+}
+
+TEST(AttrTable, HeaderDecodeTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 2, 0, /* attr handle */
+ 0, /* attr type */
+ 1, 0, /* attr name handle (string handle) */
+ 2, /* number of possible value */
+ 2, 0, /* possible value handle */
+ 3, 0, /* possible value handle */
+ 1, /* number of default value */
+ 0 /* defaut value string handle index */
+ };
+ auto entry =
+ reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
+ auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
+ EXPECT_EQ(attrHandle, 2);
+ auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
+ EXPECT_EQ(attrType, 0);
+ auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
+ EXPECT_EQ(stringHandle, 1);
+}
+
+TEST(AttrTable, EnumEntryDecodeTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 1, 0, /* attr name handle */
+ 2, /* number of possible value */
+ 2, 0, /* possible value handle */
+ 3, 0, /* possible value handle */
+ 1, /* number of default value */
+ 1 /* defaut value string handle index */
+ };
+
+ auto entry =
+ reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
+ uint8_t pvNumber = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
+ EXPECT_EQ(pvNumber, 2);
+ pvNumber = 0;
+ auto rc =
+ pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(pvNumber, 2);
+
+ std::vector<uint16_t> pvHandles(pvNumber, 0);
+ pvNumber = pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+ entry, pvHandles.data(), pvHandles.size());
+ EXPECT_EQ(pvNumber, 2);
+ EXPECT_EQ(pvHandles[0], 2);
+ EXPECT_EQ(pvHandles[1], 3);
+ pvHandles.resize(1);
+ pvNumber = pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+ entry, pvHandles.data(), pvHandles.size());
+ EXPECT_EQ(pvNumber, 1);
+ EXPECT_EQ(pvHandles[0], 2);
+
+ pvHandles.resize(2);
+ rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
+ entry, pvHandles.data(), pvHandles.size());
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(pvHandles[0], 2);
+ EXPECT_EQ(pvHandles[1], 3);
+ rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
+ entry, pvHandles.data(), 1);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ uint8_t defNumber = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
+ EXPECT_EQ(defNumber, 1);
+ std::vector<uint8_t> defIndices(defNumber);
+ rc = pldm_bios_table_attr_entry_enum_decode_def_indices(
+ entry, defIndices.data(), defIndices.size());
+ EXPECT_EQ(rc, defNumber);
+ EXPECT_THAT(defIndices, ElementsAreArray({1}));
+
+ defNumber = 0;
+ rc =
+ pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(defNumber, 1);
+
+ rc =
+ pldm_bios_table_attr_entry_enum_decode_pv_num_check(nullptr, &pvNumber);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ entry->attr_type = PLDM_BIOS_STRING;
+ rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc =
+ pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc =
+ pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, nullptr, 0);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(AttrTable, EnumEntryEncodeTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 1, 0, /* attr name handle */
+ 2, /* number of possible value */
+ 2, 0, /* possible value handle */
+ 3, 0, /* possible value handle */
+ 1, /* number of default value */
+ 0 /* defaut value string handle index */
+ };
+
+ std::vector<uint16_t> pv_hdls{2, 3};
+ std::vector<uint8_t> defs{0};
+
+ struct pldm_bios_table_attr_entry_enum_info info = {
+ 1, /* name handle */
+ false, /* read only */
+ 2, /* pv number */
+ pv_hdls.data(), /* pv handle */
+ 1, /*def number */
+ defs.data() /*def index*/
+ };
+ auto encodeLength = pldm_bios_table_attr_entry_enum_encode_length(2, 1);
+ EXPECT_EQ(encodeLength, enumEntry.size());
+
+ std::vector<uint8_t> encodeEntry(encodeLength, 0);
+ pldm_bios_table_attr_entry_enum_encode(encodeEntry.data(),
+ encodeEntry.size(), &info);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(enumEntry, encodeEntry);
+
+ EXPECT_DEATH(pldm_bios_table_attr_entry_enum_encode(
+ encodeEntry.data(), encodeEntry.size() - 1, &info),
+ "length <= entry_length");
+ auto rc = pldm_bios_table_attr_entry_enum_encode_check(
+ encodeEntry.data(), encodeEntry.size(), &info);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(enumEntry, encodeEntry);
+ rc = pldm_bios_table_attr_entry_enum_encode_check(
+ encodeEntry.data(), encodeEntry.size() - 1, &info);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(AttrTable, StringEntryDecodeTest)
+{
+ std::vector<uint8_t> stringEntry{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 12, 0, /* attr name handle */
+ 1, /* string type */
+ 1, 0, /* minimum length of the string in bytes */
+ 100, 0, /* maximum length of the string in bytes */
+ 3, 0, /* length of default string in length */
+ 'a', 'b', 'c' /* default string */
+ };
+
+ auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
+ stringEntry.data());
+ auto stringType =
+ pldm_bios_table_attr_entry_string_decode_string_type(entry);
+ EXPECT_EQ(stringType, 1);
+ auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
+ EXPECT_EQ(minLength, 1);
+ auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
+ EXPECT_EQ(maxLength, 100);
+
+ uint16_t defStringLength =
+ pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
+ EXPECT_EQ(defStringLength, 3);
+ std::vector<char> defString(defStringLength + 1);
+ auto rc = pldm_bios_table_attr_entry_string_decode_def_string(
+ entry, defString.data(), defString.size());
+ EXPECT_EQ(rc, 3);
+ EXPECT_STREQ(defString.data(), "abc");
+ rc = pldm_bios_table_attr_entry_string_decode_def_string(
+ entry, defString.data(), defString.size() - 1);
+ EXPECT_EQ(rc, 2);
+ EXPECT_STREQ(defString.data(), "ab");
+
+ defStringLength = 0;
+ rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
+ entry, &defStringLength);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(defStringLength, 3);
+
+ rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
+ entry, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
+ nullptr, &defStringLength);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ entry->attr_type = PLDM_BIOS_INTEGER;
+ rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
+ entry, &defStringLength);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
+ nullptr, &defStringLength);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(AttrTable, StringEntryEncodeTest)
+{
+ std::vector<uint8_t> stringEntry{
+ 0, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* attr name handle */
+ 1, /* string type */
+ 1, 0, /* min string length */
+ 100, 0, /* max string length */
+ 3, 0, /* default string length */
+ 'a', 'b', 'c', /* defaul string */
+ };
+
+ struct pldm_bios_table_attr_entry_string_info info = {
+ 3, /* name handle */
+ false, /* read only */
+ 1, /* string type ascii */
+ 1, /* min length */
+ 100, /* max length */
+ 3, /* def length */
+ "abc", /* def string */
+ };
+ auto encodeLength = pldm_bios_table_attr_entry_string_encode_length(3);
+ EXPECT_EQ(encodeLength, stringEntry.size());
+
+ std::vector<uint8_t> encodeEntry(encodeLength, 0);
+ pldm_bios_table_attr_entry_string_encode(encodeEntry.data(),
+ encodeEntry.size(), &info);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(stringEntry, encodeEntry);
+
+ EXPECT_DEATH(pldm_bios_table_attr_entry_string_encode(
+ encodeEntry.data(), encodeEntry.size() - 1, &info),
+ "length <= entry_length");
+ auto rc = pldm_bios_table_attr_entry_string_encode_check(
+ encodeEntry.data(), encodeEntry.size(), &info);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(stringEntry, encodeEntry);
+ rc = pldm_bios_table_attr_entry_string_encode_check(
+ encodeEntry.data(), encodeEntry.size() - 1, &info);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+ std::swap(info.max_length, info.min_length);
+ const char* errmsg;
+ rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ EXPECT_STREQ(
+ "MinimumStingLength should not be greater than MaximumStringLength",
+ errmsg);
+ rc = pldm_bios_table_attr_entry_string_encode_check(
+ encodeEntry.data(), encodeEntry.size(), &info);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ std::swap(info.max_length, info.min_length);
+
+ std::vector<uint8_t> stringEntryLength0{
+ 0, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* attr name handle */
+ 1, /* string type */
+ 1, 0, /* min string length */
+ 100, 0, /* max string length */
+ 0, 0, /* default string length */
+ };
+
+ info.def_length = 0;
+ info.def_string = nullptr;
+
+ encodeLength = pldm_bios_table_attr_entry_string_encode_length(0);
+ EXPECT_EQ(encodeLength, stringEntryLength0.size());
+
+ encodeEntry.resize(encodeLength);
+ pldm_bios_table_attr_entry_string_encode(encodeEntry.data(),
+ encodeEntry.size(), &info);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(stringEntryLength0, encodeEntry);
+}
+
+TEST(AttrTable, integerEntryEncodeTest)
+{
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 1, 0, /* attr name handle */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* lower bound */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
+ 2, 0, 0, 0, /* scalar increment */
+ 3, 0, 0, 0, 0, 0, 0, 0, /* defaut value */
+ };
+
+ std::vector<uint16_t> pv_hdls{2, 3};
+ std::vector<uint8_t> defs{0};
+
+ struct pldm_bios_table_attr_entry_integer_info info = {
+ 1, /* name handle */
+ false, /* read only */
+ 1, /* lower bound */
+ 10, /* upper bound */
+ 2, /* sacalar increment */
+ 3 /* default value */
+ };
+ auto encodeLength = pldm_bios_table_attr_entry_integer_encode_length();
+ EXPECT_EQ(encodeLength, integerEntry.size());
+
+ std::vector<uint8_t> encodeEntry(encodeLength, 0);
+ pldm_bios_table_attr_entry_integer_encode(encodeEntry.data(),
+ encodeEntry.size(), &info);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(integerEntry, encodeEntry);
+
+ EXPECT_DEATH(pldm_bios_table_attr_entry_integer_encode(
+ encodeEntry.data(), encodeEntry.size() - 1, &info),
+ "length <= entry_length");
+
+ auto rc = pldm_bios_table_attr_entry_integer_encode_check(
+ encodeEntry.data(), encodeEntry.size(), &info);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ // set attr handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(integerEntry, encodeEntry);
+
+ rc = pldm_bios_table_attr_entry_integer_encode_check(
+ encodeEntry.data(), encodeEntry.size() - 1, &info);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+ info.lower_bound = 100;
+ info.upper_bound = 50;
+ const char* errmsg;
+ rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ EXPECT_STREQ("LowerBound should not be greater than UpperBound", errmsg);
+ rc = pldm_bios_table_attr_entry_integer_encode_check(
+ encodeEntry.data(), encodeEntry.size(), &info);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(AttrTable, integerEntryDecodeTest)
+{
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 1, 0, /* attr name handle */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* lower bound */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
+ 2, 0, 0, 0, /* scalar increment */
+ 3, 0, 0, 0, 0, 0, 0, 0, /* defaut value */
+ };
+
+ uint64_t lower, upper, def;
+ uint32_t scalar;
+ auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
+ integerEntry.data());
+ pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
+ &def);
+ EXPECT_EQ(lower, 1);
+ EXPECT_EQ(upper, 10);
+ EXPECT_EQ(scalar, 2);
+ EXPECT_EQ(def, 3);
+}
+
+TEST(AttrTable, ItearatorTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 1, 0, /* attr name handle */
+ 2, /* number of possible value */
+ 2, 0, /* possible value handle */
+ 3, 0, /* possible value handle */
+ 1, /* number of default value */
+ 0 /* defaut value string handle index */
+ };
+ std::vector<uint8_t> stringEntry{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 12, 0, /* attr name handle */
+ 1, /* string type */
+ 1, 0, /* minimum length of the string in bytes */
+ 100, 0, /* maximum length of the string in bytes */
+ 3, 0, /* length of default string in length */
+ 'a', 'b', 'c' /* default string */
+ };
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 1, 0, /* attr name handle */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* lower bound */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
+ 2, 0, 0, 0, /* scalar increment */
+ 3, 0, 0, 0, 0, 0, 0, 0, /* defaut value */
+ };
+
+ Table table;
+ buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
+ auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
+ PLDM_BIOS_ATTR_TABLE);
+ auto entry = pldm_bios_table_iter_attr_entry_value(iter);
+ auto rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
+ EXPECT_EQ(rc, 0);
+
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_attr_entry_value(iter);
+ rc = std::memcmp(entry, stringEntry.data(), stringEntry.size());
+ EXPECT_EQ(rc, 0);
+
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_attr_entry_value(iter);
+ rc = std::memcmp(entry, integerEntry.data(), integerEntry.size());
+ EXPECT_EQ(rc, 0);
+
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_attr_entry_value(iter);
+ rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
+ EXPECT_EQ(rc, 0);
+
+ pldm_bios_table_iter_next(iter);
+ EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
+ pldm_bios_table_iter_free(iter);
+}
+
+TEST(AttrTable, FindTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 1, 0, /* attr name handle */
+ 2, /* number of possible value */
+ 2, 0, /* possible value handle */
+ 3, 0, /* possible value handle */
+ 1, /* number of default value */
+ 0 /* defaut value string handle index */
+ };
+ std::vector<uint8_t> stringEntry{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 12, 0, /* attr name handle */
+ 1, /* string type */
+ 1, 0, /* minimum length of the string in bytes */
+ 100, 0, /* maximum length of the string in bytes */
+ 3, 0, /* length of default string in length */
+ 'a', 'b', 'c' /* default string */
+ };
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 1, 0, /* attr name handle */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* lower bound */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
+ 2, 0, 0, 0, /* scalar increment */
+ 3, 0, 0, 0, 0, 0, 0, 0, /* defaut value */
+ };
+
+ Table table;
+ buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
+
+ auto entry =
+ pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 1);
+ EXPECT_NE(entry, nullptr);
+ auto p = reinterpret_cast<const uint8_t*>(entry);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
+ ElementsAreArray(stringEntry));
+
+ entry = pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 3);
+ EXPECT_EQ(entry, nullptr);
+}
+
+TEST(AttrValTable, HeaderDecodeTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 1, 0, /* attr handle */
+ 0, /* attr type */
+ 2, /* number of current value */
+ 0, /* current value string handle index */
+ 1, /* current value string handle index */
+ };
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ enumEntry.data());
+ auto attrHandle =
+ pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
+ EXPECT_EQ(attrHandle, 1);
+ auto attrType =
+ pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
+ EXPECT_EQ(attrType, 0);
+}
+
+TEST(AttrValTable, EnumEntryEncodeTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 2, /* number of current value */
+ 0, /* current value string handle index */
+ 1, /* current value string handle index */
+ };
+
+ auto length = pldm_bios_table_attr_value_entry_encode_enum_length(2);
+ EXPECT_EQ(length, enumEntry.size());
+ std::vector<uint8_t> encodeEntry(length, 0);
+ uint8_t handles[] = {0, 1};
+ pldm_bios_table_attr_value_entry_encode_enum(
+ encodeEntry.data(), encodeEntry.size(), 0, 0, 2, handles);
+ EXPECT_EQ(encodeEntry, enumEntry);
+
+ EXPECT_DEATH(
+ pldm_bios_table_attr_value_entry_encode_enum(
+ encodeEntry.data(), encodeEntry.size() - 1, 0, 0, 2, handles),
+ "length <= entry_length");
+
+ auto rc = pldm_bios_table_attr_value_entry_encode_enum_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_ENUMERATION, 2,
+ handles);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(encodeEntry, enumEntry);
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ enumEntry.data());
+ entry->attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY;
+ rc = pldm_bios_table_attr_value_entry_encode_enum_check(
+ encodeEntry.data(), encodeEntry.size(), 0,
+ PLDM_BIOS_ENUMERATION_READ_ONLY, 2, handles);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(encodeEntry, enumEntry);
+ rc = pldm_bios_table_attr_value_entry_encode_enum_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 2,
+ handles);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = pldm_bios_table_attr_value_entry_encode_enum_check(
+ encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_ENUMERATION, 2,
+ handles);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(AttrValTable, EnumEntryDecodeTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 2, /* number of current value */
+ 0, /* current value string handle index */
+ 1, /* current value string handle index */
+ };
+
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ enumEntry.data());
+ auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
+ EXPECT_EQ(2, number);
+
+ std::vector<uint8_t> handles(2, 0);
+ auto rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
+ entry, handles.data(), handles.size());
+ EXPECT_EQ(rc, 2);
+ EXPECT_EQ(handles[0], 0);
+ EXPECT_EQ(handles[1], 1);
+}
+
+TEST(AttrValTable, stringEntryEncodeTest)
+{
+ std::vector<uint8_t> stringEntry{
+ 0, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* current string length */
+ 'a', 'b', 'c', /* defaut value string handle index */
+ };
+
+ auto length = pldm_bios_table_attr_value_entry_encode_string_length(3);
+ EXPECT_EQ(length, stringEntry.size());
+ std::vector<uint8_t> encodeEntry(length, 0);
+ pldm_bios_table_attr_value_entry_encode_string(
+ encodeEntry.data(), encodeEntry.size(), 0, 1, 3, "abc");
+ EXPECT_EQ(encodeEntry, stringEntry);
+
+ EXPECT_DEATH(
+ pldm_bios_table_attr_value_entry_encode_string(
+ encodeEntry.data(), encodeEntry.size() - 1, 0, 1, 3, "abc"),
+ "length <= entry_length");
+
+ auto rc = pldm_bios_table_attr_value_entry_encode_string_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING, 3, "abc");
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(encodeEntry, stringEntry);
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ stringEntry.data());
+ entry->attr_type = PLDM_BIOS_STRING_READ_ONLY;
+ rc = pldm_bios_table_attr_value_entry_encode_string_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING_READ_ONLY,
+ 3, "abc");
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(encodeEntry, stringEntry);
+ rc = pldm_bios_table_attr_value_entry_encode_string_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 3,
+ "abc");
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = pldm_bios_table_attr_value_entry_encode_string_check(
+ encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_STRING, 3,
+ "abc");
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(AttrValTable, StringEntryDecodeTest)
+{
+ std::vector<uint8_t> stringEntry{
+ 0, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* current string length */
+ 'a', 'b', 'c', /* defaut value string handle index */
+ };
+
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ stringEntry.data());
+ auto length = pldm_bios_table_attr_value_entry_string_decode_length(entry);
+ EXPECT_EQ(3, length);
+
+ auto handle = pldm_bios_table_attr_value_entry_decode_handle(entry);
+ EXPECT_EQ(0, handle);
+
+ auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
+ EXPECT_EQ(stringEntry.size(), entryLength);
+
+ variable_field currentString{};
+ pldm_bios_table_attr_value_entry_string_decode_string(entry,
+ ¤tString);
+ EXPECT_THAT(std::vector<uint8_t>(currentString.ptr,
+ currentString.ptr + currentString.length),
+ ElementsAreArray(std::vector<uint8_t>{'a', 'b', 'c'}));
+}
+
+TEST(AttrValTable, integerEntryEncodeTest)
+{
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+ };
+
+ auto length = pldm_bios_table_attr_value_entry_encode_integer_length();
+ EXPECT_EQ(length, integerEntry.size());
+ std::vector<uint8_t> encodeEntry(length, 0);
+ pldm_bios_table_attr_value_entry_encode_integer(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER, 10);
+ EXPECT_EQ(encodeEntry, integerEntry);
+
+ EXPECT_DEATH(pldm_bios_table_attr_value_entry_encode_integer(
+ encodeEntry.data(), encodeEntry.size() - 1, 0,
+ PLDM_BIOS_INTEGER, 10),
+ "length <= entry_length");
+
+ auto rc = pldm_bios_table_attr_value_entry_encode_integer_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER, 10);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(encodeEntry, integerEntry);
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ integerEntry.data());
+ entry->attr_type = PLDM_BIOS_INTEGER_READ_ONLY;
+ rc = pldm_bios_table_attr_value_entry_encode_integer_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER_READ_ONLY,
+ 10);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(encodeEntry, integerEntry);
+
+ rc = pldm_bios_table_attr_value_entry_encode_integer_check(
+ encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 10);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = pldm_bios_table_attr_value_entry_encode_integer_check(
+ encodeEntry.data(), encodeEntry.size() - 1, 0,
+ PLDM_BIOS_INTEGER_READ_ONLY, 10);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(AttrValTable, integerEntryDecodeTest)
+{
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+ };
+
+ auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ integerEntry.data());
+ auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
+ EXPECT_EQ(cv, 10);
+}
+
+TEST(AttrValTable, IteratorTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 2, /* number of current value */
+ 0, /* current value string handle index */
+ 1, /* current value string handle index */
+ };
+ std::vector<uint8_t> stringEntry{
+ 0, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* current string length */
+ 'a', 'b', 'c', /* defaut value string handle index */
+ };
+ std::vector<uint8_t> integerEntry{
+ 0, 0, /* attr handle */
+ 3, /* attr type */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+ };
+
+ Table table;
+ buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
+
+ auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
+ PLDM_BIOS_ATTR_VAL_TABLE);
+ auto entry = pldm_bios_table_iter_attr_value_entry_value(iter);
+
+ auto p = reinterpret_cast<const uint8_t*>(entry);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + enumEntry.size()),
+ ElementsAreArray(enumEntry));
+
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_attr_value_entry_value(iter);
+ p = reinterpret_cast<const uint8_t*>(entry);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
+ ElementsAreArray(stringEntry));
+
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_attr_value_entry_value(iter);
+ p = reinterpret_cast<const uint8_t*>(entry);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + integerEntry.size()),
+ ElementsAreArray(integerEntry));
+
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_attr_value_entry_value(iter);
+ p = reinterpret_cast<const uint8_t*>(entry);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + enumEntry.size()),
+ ElementsAreArray(enumEntry));
+
+ pldm_bios_table_iter_next(iter);
+ EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
+
+ pldm_bios_table_iter_free(iter);
+}
+
+TEST(AttrValTable, FindTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 2, /* number of current value */
+ 0, /* current value string handle index */
+ 1, /* current value string handle index */
+ };
+ std::vector<uint8_t> stringEntry{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* current string length */
+ 'a', 'b', 'c', /* defaut value string handle index */
+ };
+ std::vector<uint8_t> integerEntry{
+ 2, 0, /* attr handle */
+ 3, /* attr type */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+ };
+
+ Table table;
+ buildTable(table, enumEntry, stringEntry, integerEntry);
+
+ auto entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
+ table.size(), 1);
+ EXPECT_NE(entry, nullptr);
+ auto p = reinterpret_cast<const uint8_t*>(entry);
+ EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
+ ElementsAreArray(stringEntry));
+
+ entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
+ table.size(), 3);
+ EXPECT_EQ(entry, nullptr);
+
+ auto firstEntry =
+ reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(table.data());
+ firstEntry->attr_type = PLDM_BIOS_PASSWORD;
+ EXPECT_DEATH(pldm_bios_table_attr_value_find_by_handle(table.data(),
+ table.size(), 1),
+ "entry_length != NULL");
+}
+
+TEST(AttrValTable, CopyAndUpdateTest)
+{
+ std::vector<uint8_t> enumEntry{
+ 0, 0, /* attr handle */
+ 0, /* attr type */
+ 2, /* number of current value */
+ 0, /* current value string handle index */
+ 1, /* current value string handle index */
+ };
+ std::vector<uint8_t> stringEntry{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* current string length */
+ 'a', 'b', 'c', /* defaut value string handle index */
+ };
+ std::vector<uint8_t> integerEntry{
+ 2, 0, /* attr handle */
+ 3, /* attr type */
+ 10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+ };
+
+ Table srcTable;
+ buildTable(srcTable, enumEntry, stringEntry, integerEntry);
+
+ std::vector<uint8_t> stringEntry1{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 3, 0, /* current string length */
+ 'd', 'e', 'f', /* defaut value string handle index */
+ };
+
+ Table expectTable;
+ buildTable(expectTable, enumEntry, stringEntry1, integerEntry);
+ Table destTable(expectTable.size() + 10);
+ auto destLength = destTable.size();
+ auto rc = pldm_bios_table_attr_value_copy_and_update(
+ srcTable.data(), srcTable.size(), destTable.data(), &destLength,
+ stringEntry1.data(), stringEntry1.size());
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(destLength, expectTable.size());
+ destTable.resize(destLength);
+ EXPECT_THAT(destTable, ElementsAreArray(expectTable));
+
+ std::vector<uint8_t> stringEntry2{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 5, 0, /* current string length */
+ 'd', 'e', 'f', 'a', 'b', /* defaut value string handle index */
+ };
+ expectTable.resize(0);
+ buildTable(expectTable, enumEntry, stringEntry2, integerEntry);
+ destTable.resize(expectTable.size() + 10);
+ destLength = destTable.size();
+ rc = pldm_bios_table_attr_value_copy_and_update(
+ srcTable.data(), srcTable.size(), destTable.data(), &destLength,
+ stringEntry2.data(), stringEntry2.size());
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(destLength, expectTable.size());
+ destTable.resize(destLength);
+ EXPECT_THAT(destTable, ElementsAreArray(expectTable));
+
+ std::vector<uint8_t> stringEntry3{
+ 1, 0, /* attr handle */
+ 1, /* attr type */
+ 1, 0, /* current string length */
+ 'd', /* defaut value string handle index */
+ };
+ expectTable.resize(0);
+ buildTable(expectTable, enumEntry, stringEntry3, integerEntry);
+ destTable.resize(expectTable.size() + 10);
+ destLength = destTable.size();
+ rc = pldm_bios_table_attr_value_copy_and_update(
+ srcTable.data(), srcTable.size(), destTable.data(), &destLength,
+ stringEntry3.data(), stringEntry3.size());
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(destLength, expectTable.size());
+ destTable.resize(destLength);
+ EXPECT_THAT(destTable, ElementsAreArray(expectTable));
+
+ stringEntry3[2] = PLDM_BIOS_INTEGER; // set attribute type to integer
+ rc = pldm_bios_table_attr_value_copy_and_update(
+ srcTable.data(), srcTable.size(), destTable.data(), &destLength,
+ stringEntry3.data(), stringEntry3.size());
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ stringEntry3[2] = PLDM_BIOS_STRING; // set attribute type to string
+
+ destTable.resize(expectTable.size() - 1);
+ destLength = destTable.size();
+ rc = pldm_bios_table_attr_value_copy_and_update(
+ srcTable.data(), srcTable.size(), destTable.data(), &destLength,
+ stringEntry3.data(), stringEntry3.size());
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(StringTable, EntryEncodeTest)
+{
+ std::vector<uint8_t> stringEntry{
+ 0, 0, /* string handle*/
+ 7, 0, /* string length */
+ 'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
+ };
+
+ const char* str = "Allowed";
+ auto str_length = std::strlen(str);
+ auto encodeLength = pldm_bios_table_string_entry_encode_length(str_length);
+ EXPECT_EQ(encodeLength, stringEntry.size());
+
+ std::vector<uint8_t> encodeEntry(encodeLength, 0);
+ pldm_bios_table_string_entry_encode(encodeEntry.data(), encodeEntry.size(),
+ str, str_length);
+ // set string handle = 0
+ encodeEntry[0] = 0;
+ encodeEntry[1] = 0;
+
+ EXPECT_EQ(stringEntry, encodeEntry);
+
+ EXPECT_DEATH(pldm_bios_table_string_entry_encode(encodeEntry.data(),
+ encodeEntry.size() - 1,
+ str, str_length),
+ "length <= entry_length");
+ auto rc = pldm_bios_table_string_entry_encode_check(
+ encodeEntry.data(), encodeEntry.size() - 1, str, str_length);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(StringTable, EntryDecodeTest)
+{
+ std::vector<uint8_t> stringEntry{
+ 4, 0, /* string handle*/
+ 7, 0, /* string length */
+ 'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
+ };
+ auto entry = reinterpret_cast<struct pldm_bios_string_table_entry*>(
+ stringEntry.data());
+ auto handle = pldm_bios_table_string_entry_decode_handle(entry);
+ EXPECT_EQ(handle, 4);
+ auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
+ EXPECT_EQ(strLength, 7);
+
+ std::vector<char> buffer(strLength + 1, 0);
+ auto decodedLength = pldm_bios_table_string_entry_decode_string(
+ entry, buffer.data(), buffer.size());
+ EXPECT_EQ(decodedLength, strLength);
+ EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
+ decodedLength = pldm_bios_table_string_entry_decode_string(
+ entry, buffer.data(), 2 + 1 /* sizeof '\0'*/);
+ EXPECT_EQ(decodedLength, 2);
+ EXPECT_EQ(std::strcmp("Al", buffer.data()), 0);
+
+ auto rc = pldm_bios_table_string_entry_decode_string_check(
+ entry, buffer.data(), buffer.size());
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
+
+ rc = pldm_bios_table_string_entry_decode_string_check(entry, buffer.data(),
+ buffer.size() - 1);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(StringTable, IteratorTest)
+{
+ std::vector<uint8_t> stringHello{
+ 0, 0, /* string handle*/
+ 5, 0, /* string length */
+ 'H', 'e', 'l', 'l', 'o', /* string */
+ };
+ std::vector<uint8_t> stringWorld{
+ 1, 0, /* string handle*/
+ 6, 0, /* string length */
+ 'W', 'o', 'r', 'l', 'd', '!', /* string */
+ };
+
+ Table table;
+ buildTable(table, stringHello, stringWorld);
+
+ auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
+ PLDM_BIOS_STRING_TABLE);
+ auto entry = pldm_bios_table_iter_string_entry_value(iter);
+ auto rc = std::memcmp(entry, stringHello.data(), stringHello.size());
+ EXPECT_EQ(rc, 0);
+ pldm_bios_table_iter_next(iter);
+ entry = pldm_bios_table_iter_string_entry_value(iter);
+ rc = std::memcmp(entry, stringWorld.data(), stringWorld.size());
+ EXPECT_EQ(rc, 0);
+ pldm_bios_table_iter_next(iter);
+ EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
+ pldm_bios_table_iter_free(iter);
+}
+
+TEST(StringTable, FindTest)
+{
+ std::vector<uint8_t> stringHello{
+ 1, 0, /* string handle*/
+ 5, 0, /* string length */
+ 'H', 'e', 'l', 'l', 'o', /* string */
+ };
+ std::vector<uint8_t> stringWorld{
+ 2, 0, /* string handle*/
+ 6, 0, /* string length */
+ 'W', 'o', 'r', 'l', 'd', '!', /* string */
+ };
+ std::vector<uint8_t> stringHi{
+ 3, 0, /* string handle*/
+ 2, 0, /* string length */
+ 'H', 'i', /* string */
+ };
+
+ Table table;
+ buildTable(table, stringHello, stringWorld, stringHi);
+
+ auto entry = pldm_bios_table_string_find_by_string(table.data(),
+ table.size(), "World!");
+ EXPECT_NE(entry, nullptr);
+ auto handle = pldm_bios_table_string_entry_decode_handle(entry);
+ EXPECT_EQ(handle, 2);
+
+ entry = pldm_bios_table_string_find_by_string(table.data(), table.size(),
+ "Worl");
+ EXPECT_EQ(entry, nullptr);
+
+ entry =
+ pldm_bios_table_string_find_by_handle(table.data(), table.size(), 3);
+ EXPECT_NE(entry, nullptr);
+ auto str_length = pldm_bios_table_string_entry_decode_string_length(entry);
+ EXPECT_EQ(str_length, 2);
+ std::vector<char> strBuf(str_length + 1, 0);
+ auto rc = pldm_bios_table_string_entry_decode_string_check(
+ entry, strBuf.data(), strBuf.size());
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(std::strcmp("Hi", strBuf.data()), 0);
+
+ entry =
+ pldm_bios_table_string_find_by_handle(table.data(), table.size(), 4);
+ EXPECT_EQ(entry, nullptr);
+}
+
+TEST(Itearator, DeathTest)
+{
+
+ Table table(256, 0);
+
+ /* first entry */
+ auto attr_entry =
+ reinterpret_cast<struct pldm_bios_attr_table_entry*>(table.data());
+ auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
+ PLDM_BIOS_ATTR_TABLE);
+ attr_entry->attr_type = PLDM_BIOS_PASSWORD;
+ EXPECT_DEATH(pldm_bios_table_iter_next(iter), "attr_table_entry != NULL");
+ pldm_bios_table_iter_free(iter);
+}
+
+TEST(PadAndChecksum, PadAndChecksum)
+{
+ EXPECT_EQ(4, pldm_bios_table_pad_checksum_size(0));
+ EXPECT_EQ(7, pldm_bios_table_pad_checksum_size(1));
+ EXPECT_EQ(6, pldm_bios_table_pad_checksum_size(2));
+ EXPECT_EQ(5, pldm_bios_table_pad_checksum_size(3));
+ EXPECT_EQ(4, pldm_bios_table_pad_checksum_size(4));
+
+ // The table is borrowed from
+ // https://github.com/openbmc/pldm/commit/69d3e7fb2d9935773f4fbf44326c33f3fc0a3c38
+ // refer to the commit message
+ Table attrValTable = {0x09, 0x00, 0x01, 0x02, 0x00, 0x65, 0x66};
+ auto sizeWithoutPad = attrValTable.size();
+ attrValTable.resize(sizeWithoutPad +
+ pldm_bios_table_pad_checksum_size(sizeWithoutPad));
+ pldm_bios_table_append_pad_checksum(attrValTable.data(),
+ attrValTable.size(), sizeWithoutPad);
+ Table expectedTable = {0x09, 0x00, 0x01, 0x02, 0x00, 0x65,
+ 0x66, 0x00, 0x6d, 0x81, 0x4a, 0xb6};
+ EXPECT_EQ(attrValTable, expectedTable);
+}
diff --git a/libpldm/tests/libpldm_bios_test.cpp b/libpldm/tests/libpldm_bios_test.cpp
new file mode 100644
index 0000000..ad07877
--- /dev/null
+++ b/libpldm/tests/libpldm_bios_test.cpp
@@ -0,0 +1,821 @@
+#include <string.h>
+
+#include <array>
+
+#include "libpldm/base.h"
+#include "libpldm/bios.h"
+#include "libpldm/utils.h"
+
+#include <gtest/gtest.h>
+
+constexpr auto hdrSize = sizeof(pldm_msg_hdr);
+
+TEST(GetDateTime, testEncodeRequest)
+{
+ pldm_msg request{};
+
+ auto rc = encode_get_date_time_req(0, &request);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+}
+
+TEST(GetDateTime, testEncodeResponse)
+{
+ uint8_t completionCode = 0;
+ uint8_t seconds = 50;
+ uint8_t minutes = 20;
+ uint8_t hours = 5;
+ uint8_t day = 23;
+ uint8_t month = 11;
+ uint16_t year = 2019;
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES>
+ responseMsg{};
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = encode_get_date_time_resp(0, PLDM_SUCCESS, seconds, minutes,
+ hours, day, month, year, response);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, response->payload[0]);
+
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]),
+ &seconds, sizeof(seconds)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(seconds),
+ &minutes, sizeof(minutes)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(seconds) + sizeof(minutes),
+ &hours, sizeof(hours)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(seconds) + sizeof(minutes) + sizeof(hours),
+ &day, sizeof(day)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(seconds) + sizeof(minutes) + sizeof(hours) +
+ sizeof(day),
+ &month, sizeof(month)));
+ EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
+ sizeof(seconds) + sizeof(minutes) + sizeof(hours) +
+ sizeof(day) + sizeof(month),
+ &year, sizeof(year)));
+}
+
+TEST(GetDateTime, testDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_DATE_TIME_RESP_BYTES> responseMsg{};
+
+ uint8_t completionCode = 0;
+
+ uint8_t seconds = 55;
+ uint8_t minutes = 2;
+ uint8_t hours = 8;
+ uint8_t day = 9;
+ uint8_t month = 7;
+ uint16_t year = 2020;
+
+ uint8_t retSeconds = 0;
+ uint8_t retMinutes = 0;
+ uint8_t retHours = 0;
+ uint8_t retDay = 0;
+ uint8_t retMonth = 0;
+ uint16_t retYear = 0;
+
+ memcpy(responseMsg.data() + sizeof(completionCode) + hdrSize, &seconds,
+ sizeof(seconds));
+ memcpy(responseMsg.data() + sizeof(completionCode) + sizeof(seconds) +
+ hdrSize,
+ &minutes, sizeof(minutes));
+ memcpy(responseMsg.data() + sizeof(completionCode) + sizeof(seconds) +
+ sizeof(minutes) + hdrSize,
+ &hours, sizeof(hours));
+ memcpy(responseMsg.data() + sizeof(completionCode) + sizeof(seconds) +
+ sizeof(minutes) + sizeof(hours) + hdrSize,
+ &day, sizeof(day));
+ memcpy(responseMsg.data() + sizeof(completionCode) + sizeof(seconds) +
+ sizeof(minutes) + sizeof(hours) + sizeof(day) + hdrSize,
+ &month, sizeof(month));
+ memcpy(responseMsg.data() + sizeof(completionCode) + sizeof(seconds) +
+ sizeof(minutes) + sizeof(hours) + sizeof(day) + sizeof(month) +
+ hdrSize,
+ &year, sizeof(year));
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_get_date_time_resp(
+ response, responseMsg.size() - hdrSize, &completionCode, &retSeconds,
+ &retMinutes, &retHours, &retDay, &retMonth, &retYear);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(seconds, retSeconds);
+ EXPECT_EQ(minutes, retMinutes);
+ EXPECT_EQ(hours, retHours);
+ EXPECT_EQ(day, retDay);
+ EXPECT_EQ(month, retMonth);
+ EXPECT_EQ(year, retYear);
+}
+
+TEST(SetDateTime, testGoodEncodeResponse)
+{
+ uint8_t instanceId = 0;
+ uint8_t completionCode = PLDM_SUCCESS;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_only_cc_resp)>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+
+ auto rc = encode_set_date_time_resp(instanceId, completionCode, response,
+ responseMsg.size() - hdrSize);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_only_cc_resp* resp =
+ reinterpret_cast<struct pldm_only_cc_resp*>(response->payload);
+ EXPECT_EQ(completionCode, resp->completion_code);
+}
+
+TEST(SetDateTime, testBadEncodeResponse)
+{
+
+ uint8_t instanceId = 10;
+ uint8_t completionCode = PLDM_SUCCESS;
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_only_cc_resp)>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ auto rc = encode_set_date_time_resp(instanceId, completionCode, nullptr,
+ responseMsg.size() - hdrSize);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = encode_set_date_time_resp(instanceId, completionCode, response,
+ responseMsg.size() - hdrSize - 1);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetDateTime, testGoodDecodeResponse)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_only_cc_resp)>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ struct pldm_only_cc_resp* resp =
+ reinterpret_cast<struct pldm_only_cc_resp*>(response->payload);
+
+ resp->completion_code = completionCode;
+
+ uint8_t retCompletionCode;
+ auto rc = decode_set_date_time_resp(response, responseMsg.size() - hdrSize,
+ &retCompletionCode);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, retCompletionCode);
+}
+
+TEST(SetDateTime, testBadDecodeResponse)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_only_cc_resp)>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ auto rc = decode_set_date_time_resp(nullptr, responseMsg.size() - hdrSize,
+ &completionCode);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_set_date_time_resp(response, responseMsg.size() - hdrSize - 1,
+ &completionCode);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetDateTime, testGoodEncodeRequset)
+{
+ uint8_t instanceId = 0;
+ uint8_t seconds = 50;
+ uint8_t minutes = 20;
+ uint8_t hours = 10;
+ uint8_t day = 11;
+ uint8_t month = 11;
+ uint16_t year = 2019;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_set_date_time_req)>
+ requestMsg{};
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_set_date_time_req(instanceId, seconds, minutes, hours, day,
+ month, year, request,
+ requestMsg.size() - hdrSize);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_set_date_time_req* req =
+ reinterpret_cast<struct pldm_set_date_time_req*>(request->payload);
+ EXPECT_EQ(seconds, bcd2dec8(req->seconds));
+ EXPECT_EQ(minutes, bcd2dec8(req->minutes));
+ EXPECT_EQ(hours, bcd2dec8(req->hours));
+ EXPECT_EQ(day, bcd2dec8(req->day));
+ EXPECT_EQ(month, bcd2dec8(req->month));
+ EXPECT_EQ(year, le16toh(bcd2dec16(req->year)));
+}
+
+TEST(SetDateTime, testBadEncodeRequset)
+{
+ uint8_t instanceId = 0;
+
+ uint8_t seconds = 50;
+ uint8_t minutes = 20;
+ uint8_t hours = 10;
+ uint8_t day = 13;
+ uint8_t month = 11;
+ uint16_t year = 2019;
+
+ uint8_t erday = 43;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_set_date_time_req)>
+ requestMsg{};
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_set_date_time_req(instanceId, seconds, minutes, hours, day,
+ month, year, nullptr,
+ requestMsg.size() - hdrSize);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = encode_set_date_time_req(instanceId, seconds, minutes, hours, erday,
+ month, year, request,
+ requestMsg.size() - hdrSize);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = encode_set_date_time_req(instanceId, seconds, minutes, hours, day,
+ month, year, request,
+ requestMsg.size() - hdrSize - 4);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetDateTime, testGoodDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_set_date_time_req)>
+ requestMsg{};
+ uint8_t seconds = 0x50;
+ uint8_t minutes = 0x20;
+ uint8_t hours = 0x10;
+ uint8_t day = 0x11;
+ uint8_t month = 0x11;
+ uint16_t year = 0x2019;
+
+ auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
+ struct pldm_set_date_time_req* req =
+ reinterpret_cast<struct pldm_set_date_time_req*>(request->payload);
+ req->seconds = seconds;
+ req->minutes = minutes;
+ req->hours = hours;
+ req->day = day;
+ req->month = month;
+ req->year = htole16(year);
+
+ uint8_t retseconds;
+ uint8_t retminutes;
+ uint8_t rethours;
+ uint8_t retday;
+ uint8_t retmonth;
+ uint16_t retyear;
+
+ auto rc = decode_set_date_time_req(request, requestMsg.size() - hdrSize,
+ &retseconds, &retminutes, &rethours,
+ &retday, &retmonth, &retyear);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retseconds, 50);
+ EXPECT_EQ(retminutes, 20);
+ EXPECT_EQ(rethours, 10);
+ EXPECT_EQ(retday, 11);
+ EXPECT_EQ(retmonth, 11);
+ EXPECT_EQ(retyear, 2019);
+}
+
+TEST(SetDateTime, testBadDecodeRequest)
+{
+ uint8_t seconds = 0x50;
+ uint8_t minutes = 0x20;
+ uint8_t hours = 0x10;
+ uint8_t day = 0x11;
+ uint8_t month = 0x11;
+ uint16_t year = 0x2019;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_set_date_time_req)>
+ requestMsg{};
+
+ auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
+
+ decode_set_date_time_req(request, requestMsg.size() - hdrSize, &seconds,
+ &minutes, &hours, &day, &month, &year);
+
+ auto rc =
+ decode_set_date_time_req(nullptr, requestMsg.size() - hdrSize, &seconds,
+ &minutes, &hours, &day, &month, &year);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_set_date_time_req(request, requestMsg.size() - hdrSize, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_set_date_time_req(request, requestMsg.size() - hdrSize - 4,
+ &seconds, &minutes, &hours, &day, &month,
+ &year);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetBIOSTable, testGoodEncodeResponse)
+{
+ std::array<uint8_t,
+ sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + 4>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint32_t nextTransferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ std::array<uint8_t, 4> tableData{1, 2, 3, 4};
+
+ auto rc = encode_get_bios_table_resp(
+ 0, PLDM_SUCCESS, nextTransferHandle, transferFlag, tableData.data(),
+ sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + 4,
+ response);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_get_bios_table_resp* resp =
+ reinterpret_cast<struct pldm_get_bios_table_resp*>(response->payload);
+
+ EXPECT_EQ(completionCode, resp->completion_code);
+ EXPECT_EQ(nextTransferHandle, resp->next_transfer_handle);
+ EXPECT_EQ(transferFlag, resp->transfer_flag);
+ EXPECT_EQ(0, memcmp(tableData.data(), resp->table_data, tableData.size()));
+}
+
+TEST(GetBIOSTable, testBadEncodeResponse)
+{
+ uint32_t nextTransferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ std::array<uint8_t, 4> tableData{1, 2, 3, 4};
+
+ auto rc = encode_get_bios_table_resp(
+ 0, PLDM_SUCCESS, nextTransferHandle, transferFlag, tableData.data(),
+ sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + 4, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetBIOSTable, testGoodEncodeRequest)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
+ requestMsg{};
+ uint32_t transferHandle = 0x0;
+ uint8_t transferOpFlag = 0x01;
+ uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_get_bios_table_req(0, transferHandle, transferOpFlag,
+ tableType, request);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_get_bios_table_req* req =
+ reinterpret_cast<struct pldm_get_bios_table_req*>(request->payload);
+ EXPECT_EQ(transferHandle, le32toh(req->transfer_handle));
+ EXPECT_EQ(transferOpFlag, req->transfer_op_flag);
+ EXPECT_EQ(tableType, req->table_type);
+}
+
+TEST(GetBIOSTable, testBadEncodeRequest)
+{
+ uint32_t transferHandle = 0x0;
+ uint8_t transferOpFlag = 0x01;
+ uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+
+ auto rc = encode_get_bios_table_req(0, transferHandle, transferOpFlag,
+ tableType, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetBIOSTable, testGoodDecodeRequest)
+{
+ const auto hdr_size = sizeof(pldm_msg_hdr);
+ std::array<uint8_t, hdr_size + PLDM_GET_BIOS_TABLE_REQ_BYTES> requestMsg{};
+ uint32_t transferHandle = 31;
+ uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+ uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+ uint32_t retTransferHandle = 0;
+ uint8_t retTransferOpFlag = 0;
+ uint8_t retTableType = 0;
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_get_bios_table_req* request =
+ reinterpret_cast<struct pldm_get_bios_table_req*>(req->payload);
+
+ request->transfer_handle = transferHandle;
+ request->transfer_op_flag = transferOpFlag;
+ request->table_type = tableType;
+
+ auto rc = decode_get_bios_table_req(req, requestMsg.size() - hdr_size,
+ &retTransferHandle, &retTransferOpFlag,
+ &retTableType);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(transferHandle, retTransferHandle);
+ EXPECT_EQ(transferOpFlag, retTransferOpFlag);
+ EXPECT_EQ(tableType, retTableType);
+}
+TEST(GetBIOSTable, testBadDecodeRequest)
+{
+ const auto hdr_size = sizeof(pldm_msg_hdr);
+ std::array<uint8_t, hdr_size + PLDM_GET_BIOS_TABLE_REQ_BYTES> requestMsg{};
+ uint32_t transferHandle = 31;
+ uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+ uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+ uint32_t retTransferHandle = 0;
+ uint8_t retTransferOpFlag = 0;
+ uint8_t retTableType = 0;
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_get_bios_table_req* request =
+ reinterpret_cast<struct pldm_get_bios_table_req*>(req->payload);
+
+ request->transfer_handle = transferHandle;
+ request->transfer_op_flag = transferOpFlag;
+ request->table_type = tableType;
+
+ auto rc = decode_get_bios_table_req(req, requestMsg.size() - hdr_size,
+ &retTransferHandle, &retTransferOpFlag,
+ &retTableType);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(transferHandle, retTransferHandle);
+ EXPECT_EQ(transferOpFlag, retTransferOpFlag);
+ EXPECT_EQ(tableType, retTableType);
+}
+/*
+TEST(GetBIOSTable, testBadDecodeRequest)
+{
+ const auto hdr_size = sizeof(pldm_msg_hdr);
+ std::array<uint8_t, hdr_size + PLDM_GET_BIOS_TABLE_REQ_BYTES> requestMsg{};
+ uint32_t transferHandle = 31;
+ uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+ uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+ uint32_t retTransferHandle = 0;
+ uint8_t retTransferOpFlag = 0;
+ uint8_t retTableType = 0;
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_get_bios_table_req* request =
+ reinterpret_cast<struct pldm_get_bios_table_req*>(req->payload);
+
+ request->transfer_handle = transferHandle;
+ request->transfer_op_flag = transferOpFlag;
+ request->table_type = tableType;
+
+ auto rc = decode_get_bios_table_req(req, requestMsg.size() - hdr_size - 3,
+ &retTransferHandle, &retTransferOpFlag,
+ &retTableType);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}*/
+
+TEST(GetBIOSAttributeCurrentValueByHandle, testGoodDecodeRequest)
+{
+ uint32_t transferHandle = 45;
+ uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+ uint16_t attributehandle = 10;
+ uint32_t retTransferHandle = 0;
+ uint8_t retTransferOpFlag = 0;
+ uint16_t retattributehandle = 0;
+ std::array<uint8_t, hdrSize + sizeof(transferHandle) +
+ sizeof(transferOpFlag) + sizeof(attributehandle)>
+ requestMsg{};
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_get_bios_attribute_current_value_by_handle_req* request =
+ reinterpret_cast<
+ struct pldm_get_bios_attribute_current_value_by_handle_req*>(
+ req->payload);
+
+ request->transfer_handle = transferHandle;
+ request->transfer_op_flag = transferOpFlag;
+ request->attribute_handle = attributehandle;
+
+ auto rc = decode_get_bios_attribute_current_value_by_handle_req(
+ req, requestMsg.size() - hdrSize, &retTransferHandle,
+ &retTransferOpFlag, &retattributehandle);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(transferHandle, retTransferHandle);
+ EXPECT_EQ(transferOpFlag, retTransferOpFlag);
+ EXPECT_EQ(attributehandle, retattributehandle);
+}
+
+TEST(GetBIOSAttributeCurrentValueByHandle, testBadDecodeRequest)
+{
+
+ uint32_t transferHandle = 0;
+ uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+ uint16_t attribute_handle = 0;
+ uint32_t retTransferHandle = 0;
+ uint8_t retTransferOpFlag = 0;
+ uint16_t retattribute_handle = 0;
+ std::array<uint8_t, hdrSize + sizeof(transferHandle) +
+ sizeof(transferOpFlag) + sizeof(attribute_handle)>
+ requestMsg{};
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_get_bios_attribute_current_value_by_handle_req* request =
+ reinterpret_cast<
+ struct pldm_get_bios_attribute_current_value_by_handle_req*>(
+ req->payload);
+
+ request->transfer_handle = transferHandle;
+ request->transfer_op_flag = transferOpFlag;
+ request->attribute_handle = attribute_handle;
+
+ auto rc = decode_get_bios_attribute_current_value_by_handle_req(
+ NULL, requestMsg.size() - hdrSize, &retTransferHandle,
+ &retTransferOpFlag, &retattribute_handle);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ transferHandle = 31;
+ request->transfer_handle = transferHandle;
+
+ rc = decode_get_bios_attribute_current_value_by_handle_req(
+ req, 0, &retTransferHandle, &retTransferOpFlag, &retattribute_handle);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetBIOSAttributeCurrentValueByHandle, testGoodEncodeResponse)
+{
+
+ uint8_t instanceId = 10;
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint32_t nextTransferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint8_t attributeData = 44;
+ std::array<uint8_t,
+ hdrSize +
+ sizeof(pldm_get_bios_attribute_current_value_by_handle_resp)>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = encode_get_bios_current_value_by_handle_resp(
+ instanceId, completionCode, nextTransferHandle, transferFlag,
+ &attributeData, sizeof(attributeData), response);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_get_bios_attribute_current_value_by_handle_resp* resp =
+ reinterpret_cast<
+ struct pldm_get_bios_attribute_current_value_by_handle_resp*>(
+ response->payload);
+
+ EXPECT_EQ(completionCode, resp->completion_code);
+ EXPECT_EQ(nextTransferHandle, resp->next_transfer_handle);
+ EXPECT_EQ(transferFlag, resp->transfer_flag);
+ EXPECT_EQ(
+ 0, memcmp(&attributeData, resp->attribute_data, sizeof(attributeData)));
+}
+
+TEST(GetBIOSAttributeCurrentValueByHandle, testBadEncodeResponse)
+{
+ uint32_t nextTransferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint8_t attributeData = 44;
+
+ auto rc = encode_get_bios_current_value_by_handle_resp(
+ 0, PLDM_SUCCESS, nextTransferHandle, transferFlag, &attributeData,
+ sizeof(attributeData), nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ std::array<uint8_t,
+ hdrSize +
+ sizeof(pldm_get_bios_attribute_current_value_by_handle_resp)>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ rc = encode_get_bios_current_value_by_handle_resp(
+ 0, PLDM_SUCCESS, nextTransferHandle, transferFlag, nullptr,
+ sizeof(attributeData), response);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(SetBiosAttributeCurrentValue, testGoodEncodeRequest)
+{
+ uint8_t instanceId = 10;
+ uint32_t transferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint32_t attributeData = 44;
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES +
+ sizeof(attributeData)>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_set_bios_attribute_current_value_req(
+ instanceId, transferHandle, transferFlag,
+ reinterpret_cast<uint8_t*>(&attributeData), sizeof(attributeData),
+ request, requestMsg.size() - hdrSize);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_set_bios_attribute_current_value_req* req =
+ reinterpret_cast<struct pldm_set_bios_attribute_current_value_req*>(
+ request->payload);
+ EXPECT_EQ(htole32(transferHandle), req->transfer_handle);
+ EXPECT_EQ(transferFlag, req->transfer_flag);
+ EXPECT_EQ(
+ 0, memcmp(&attributeData, req->attribute_data, sizeof(attributeData)));
+}
+
+TEST(SetBiosAttributeCurrentValue, testBadEncodeRequest)
+{
+ uint8_t instanceId = 10;
+ uint32_t transferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint32_t attributeData = 44;
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_set_bios_attribute_current_value_req(
+ instanceId, transferHandle, transferFlag, nullptr, 0, nullptr, 0);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = encode_set_bios_attribute_current_value_req(
+ instanceId, transferHandle, transferFlag,
+ reinterpret_cast<uint8_t*>(&attributeData), sizeof(attributeData),
+ request, requestMsg.size() - hdrSize);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetBiosAttributeCurrentValue, testGoodDecodeRequest)
+{
+ uint32_t transferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint32_t attributeData = 44;
+
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES +
+ sizeof(attributeData)>
+ requestMsg{};
+ auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
+ struct pldm_set_bios_attribute_current_value_req* req =
+ reinterpret_cast<struct pldm_set_bios_attribute_current_value_req*>(
+ request->payload);
+ req->transfer_handle = htole32(transferHandle);
+ req->transfer_flag = transferFlag;
+ memcpy(req->attribute_data, &attributeData, sizeof(attributeData));
+
+ uint32_t retTransferHandle;
+ uint8_t retTransferFlag;
+ struct variable_field attribute;
+ auto rc = decode_set_bios_attribute_current_value_req(
+ request, requestMsg.size() - hdrSize, &retTransferHandle,
+ &retTransferFlag, &attribute);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retTransferHandle, transferHandle);
+ EXPECT_EQ(retTransferFlag, transferFlag);
+ EXPECT_EQ(attribute.length, sizeof(attributeData));
+ EXPECT_EQ(0, memcmp(attribute.ptr, &attributeData, sizeof(attributeData)));
+}
+
+TEST(SetBiosAttributeCurrentValue, testBadDecodeRequest)
+{
+ uint32_t transferHandle = 32;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ struct variable_field attribute;
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES - 1>
+ requestMsg{};
+ auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
+
+ auto rc = decode_set_bios_attribute_current_value_req(
+ nullptr, 0, &transferHandle, &transferFlag, &attribute);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ rc = decode_set_bios_attribute_current_value_req(
+ request, requestMsg.size() - hdrSize, &transferHandle, &transferFlag,
+ &attribute);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetBiosAttributeCurrentValue, testGoodEncodeResponse)
+{
+ uint8_t instanceId = 10;
+ uint32_t nextTransferHandle = 32;
+ uint8_t completionCode = PLDM_SUCCESS;
+
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ auto rc = encode_set_bios_attribute_current_value_resp(
+ instanceId, completionCode, nextTransferHandle, response);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_set_bios_attribute_current_value_resp* resp =
+ reinterpret_cast<struct pldm_set_bios_attribute_current_value_resp*>(
+ response->payload);
+ EXPECT_EQ(completionCode, resp->completion_code);
+ EXPECT_EQ(htole32(nextTransferHandle), resp->next_transfer_handle);
+}
+
+TEST(SetBiosAttributeCurrentValue, testBadEncodeResponse)
+{
+ uint8_t instanceId = 10;
+ uint32_t nextTransferHandle = 32;
+ uint8_t completionCode = PLDM_SUCCESS;
+ auto rc = encode_set_bios_attribute_current_value_resp(
+ instanceId, completionCode, nextTransferHandle, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+TEST(SetBiosAttributeCurrentValue, testGoodDecodeResponse)
+{
+ uint32_t nextTransferHandle = 32;
+ uint8_t completionCode = PLDM_SUCCESS;
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ struct pldm_set_bios_attribute_current_value_resp* resp =
+ reinterpret_cast<struct pldm_set_bios_attribute_current_value_resp*>(
+ response->payload);
+
+ resp->completion_code = completionCode;
+ resp->next_transfer_handle = htole32(nextTransferHandle);
+
+ uint8_t retCompletionCode;
+ uint32_t retNextTransferHandle;
+ auto rc = decode_set_bios_attribute_current_value_resp(
+ response, responseMsg.size() - hdrSize, &retCompletionCode,
+ &retNextTransferHandle);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, retCompletionCode);
+ EXPECT_EQ(nextTransferHandle, retNextTransferHandle);
+}
+
+TEST(SetBiosAttributeCurrentValue, testBadDecodeResponse)
+{
+ uint32_t nextTransferHandle = 32;
+ uint8_t completionCode = PLDM_SUCCESS;
+
+ std::array<uint8_t, hdrSize + PLDM_SET_BIOS_ATTR_CURR_VAL_RESP_BYTES>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+ struct pldm_set_bios_attribute_current_value_resp* resp =
+ reinterpret_cast<struct pldm_set_bios_attribute_current_value_resp*>(
+ response->payload);
+
+ resp->completion_code = completionCode;
+ resp->next_transfer_handle = htole32(nextTransferHandle);
+
+ auto rc = decode_set_bios_attribute_current_value_resp(
+ nullptr, 0, &completionCode, &nextTransferHandle);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_set_bios_attribute_current_value_resp(
+ response, responseMsg.size() - hdrSize - 1, &completionCode,
+ &nextTransferHandle);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetBIOSTable, testDecodeResponse)
+{
+ uint32_t nextTransferHandle = 32;
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t transfer_flag = PLDM_START_AND_END;
+
+ std::array<uint8_t, hdrSize + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES>
+ responseMsg{};
+ struct pldm_msg* response =
+ reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+
+ struct pldm_get_bios_table_resp* resp =
+ reinterpret_cast<struct pldm_get_bios_table_resp*>(response->payload);
+
+ resp->completion_code = completionCode;
+ resp->next_transfer_handle = htole32(nextTransferHandle);
+ resp->transfer_flag = transfer_flag;
+ size_t biosTableOffset = sizeof(completionCode) +
+ sizeof(nextTransferHandle) + sizeof(transfer_flag);
+
+ uint8_t retCompletionCode;
+ uint32_t retNextTransferHandle;
+ uint8_t retransfer_flag;
+ size_t rebiosTableOffset = 0;
+ auto rc = decode_get_bios_table_resp(
+ response, responseMsg.size(), &retCompletionCode,
+ &retNextTransferHandle, &retransfer_flag, &rebiosTableOffset);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(completionCode, retCompletionCode);
+ ASSERT_EQ(nextTransferHandle, retNextTransferHandle);
+ ASSERT_EQ(transfer_flag, retransfer_flag);
+ ASSERT_EQ(biosTableOffset, rebiosTableOffset);
+}
diff --git a/libpldm/tests/libpldm_fru_test.cpp b/libpldm/tests/libpldm_fru_test.cpp
new file mode 100644
index 0000000..7331771
--- /dev/null
+++ b/libpldm/tests/libpldm_fru_test.cpp
@@ -0,0 +1,393 @@
+#include <string.h>
+
+#include <array>
+
+#include "libpldm/base.h"
+#include "libpldm/fru.h"
+
+#include <gtest/gtest.h>
+
+TEST(GetFruRecordTableMetadata, testGoodEncodeRequest)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto rc = encode_get_fru_record_table_metadata_req(0, requestPtr);
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
+ ASSERT_EQ(requestPtr->hdr.instance_id, 0);
+ ASSERT_EQ(requestPtr->hdr.type, PLDM_FRU);
+ ASSERT_EQ(requestPtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+}
+
+TEST(GetFruRecordTableMetadata, testBadEncodeRequest)
+{
+ auto rc = encode_get_fru_record_table_metadata_req(0, NULL);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetFruRecordTableMetadata, testGoodDecodeResponse)
+{
+
+ std::vector<uint8_t> responseMsg(
+ sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+ auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+ responsePtr->payload);
+
+ responsePtr->hdr.request = PLDM_RESPONSE;
+ responsePtr->hdr.instance_id = 0;
+ responsePtr->hdr.type = PLDM_FRU;
+ responsePtr->hdr.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
+ response->completion_code = PLDM_SUCCESS;
+ response->fru_data_major_version = 0x12;
+ response->fru_data_minor_version = 0x21;
+ response->fru_table_maximum_size = 0x1234ABCD;
+ response->fru_table_length = 0x56781234;
+ response->total_record_set_identifiers = 0x34EF;
+ response->total_table_records = 0xEEEF;
+ response->checksum = 0x6543FA71;
+
+ uint8_t completion_code = 0xFF;
+ uint8_t fru_data_major_version = 0x00;
+ uint8_t fru_data_minor_version = 0x00;
+ uint32_t fru_table_maximum_size = 0x00000000;
+ uint32_t fru_table_length = 0x00000000;
+ uint16_t total_record_set_identifiers = 0x0000;
+ uint16_t total_table_records = 0x0000;
+ uint32_t checksum = 0x00000000;
+
+ auto rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(completion_code, PLDM_SUCCESS);
+ ASSERT_EQ(fru_data_major_version, 0x12);
+ ASSERT_EQ(fru_data_minor_version, 0x21);
+ ASSERT_EQ(fru_table_maximum_size, 0x1234ABCD);
+ ASSERT_EQ(fru_table_length, 0x56781234);
+ ASSERT_EQ(total_record_set_identifiers, 0x34EF);
+ ASSERT_EQ(total_table_records, 0xEEEF);
+ ASSERT_EQ(checksum, 0x6543FA71);
+
+ response->fru_data_major_version = 0x00;
+ response->fru_data_minor_version = 0x00;
+ response->fru_table_maximum_size = 0x00000000;
+ response->fru_table_length = 0x00000000;
+ response->total_record_set_identifiers = 0x0000;
+ response->total_table_records = 0x0000;
+ response->checksum = 0x00000000;
+ fru_data_major_version = 0x00;
+ fru_data_minor_version = 0x00;
+ fru_table_maximum_size = 0x00000000;
+ fru_table_length = 0x00000000;
+ total_record_set_identifiers = 0x0000;
+ total_table_records = 0x0000;
+ checksum = 0x00000000;
+ response->completion_code = PLDM_ERROR_INVALID_LENGTH;
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+ ASSERT_EQ(completion_code, PLDM_ERROR_INVALID_LENGTH);
+ ASSERT_EQ(fru_data_major_version, 0x00);
+ ASSERT_EQ(fru_data_minor_version, 0x00);
+ ASSERT_EQ(fru_table_maximum_size, 0x00000000);
+ ASSERT_EQ(fru_table_length, 0x00000000);
+ ASSERT_EQ(total_record_set_identifiers, 0x0000);
+ ASSERT_EQ(total_table_records, 0x0000);
+ ASSERT_EQ(checksum, 0x00000000);
+}
+
+TEST(GetFruRecordTableMetadata, testBadDecodeResponse)
+{
+ std::vector<uint8_t> responseMsg(
+ sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+ auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+ responsePtr->payload);
+
+ response->completion_code = PLDM_SUCCESS;
+ response->fru_data_major_version = 0x12;
+ response->fru_data_minor_version = 0x21;
+ response->fru_table_maximum_size = 0x1234ABCD;
+ response->fru_table_length = 0x56781234;
+ response->total_record_set_identifiers = 0x34EF;
+ response->total_table_records = 0xEEEF;
+ response->checksum = 0x6543FA71;
+
+ uint8_t completion_code = 0xFF;
+ uint8_t fru_data_major_version = 0x00;
+ uint8_t fru_data_minor_version = 0x00;
+ uint32_t fru_table_maximum_size = 0x00000000;
+ uint32_t fru_table_length = 0x00000000;
+ uint16_t total_record_set_identifiers = 0x0000;
+ uint16_t total_table_records = 0x0000;
+ uint32_t checksum = 0x00000000;
+
+ auto rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES + 2,
+ &completion_code, &fru_data_major_version, &fru_data_minor_version,
+ &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, NULL,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ NULL, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, NULL, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, NULL,
+ &total_record_set_identifiers, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ NULL, &total_table_records, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, NULL, &checksum);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_table_metadata_resp(
+ responsePtr, payload_length, &completion_code, &fru_data_major_version,
+ &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+ &total_record_set_identifiers, &total_table_records, NULL);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetFruRecordTableMetadata, testGoodEncodeResponse)
+{
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) +
+ PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES>
+ responseMsg{};
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ responsePtr->hdr.request = PLDM_RESPONSE;
+ responsePtr->hdr.instance_id = 0;
+ responsePtr->hdr.type = PLDM_FRU;
+ responsePtr->hdr.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
+
+ uint8_t completion_code = PLDM_SUCCESS;
+ uint8_t fru_data_major_version = 0x12;
+ uint8_t fru_data_minor_version = 0x21;
+ uint32_t fru_table_maximum_size = 0x1234ABCD;
+ uint32_t fru_table_length = 0x56781234;
+ uint16_t total_record_set_identifiers = 0x34EF;
+ uint16_t total_table_records = 0xEEEF;
+ uint32_t checksum = 0x6543FA71;
+
+ auto rc = encode_get_fru_record_table_metadata_resp(
+ 0, completion_code, fru_data_major_version, fru_data_minor_version,
+ fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
+ total_table_records, checksum, responsePtr);
+
+ auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+ responsePtr->payload);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+ ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+ ASSERT_EQ(response->fru_data_major_version, 0x12);
+ ASSERT_EQ(response->fru_data_minor_version, 0x21);
+ ASSERT_EQ(response->fru_table_maximum_size, 0x1234ABCD);
+ ASSERT_EQ(response->fru_table_length, 0x56781234);
+ ASSERT_EQ(response->total_record_set_identifiers, 0x34EF);
+ ASSERT_EQ(response->total_table_records, 0xEEEF);
+ ASSERT_EQ(response->checksum, 0x6543FA71);
+
+ response->fru_data_major_version = 0;
+ response->fru_data_major_version = 0x00;
+ response->fru_data_minor_version = 0x00;
+ response->fru_table_maximum_size = 0x00000000;
+ response->fru_table_length = 0x00000000;
+ response->total_record_set_identifiers = 0x0000;
+ response->total_table_records = 0x0000;
+ response->checksum = 0x00000000;
+ completion_code = PLDM_ERROR_INVALID_DATA;
+ rc = encode_get_fru_record_table_metadata_resp(
+ 0, completion_code, fru_data_major_version, fru_data_minor_version,
+ fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
+ total_table_records, checksum, responsePtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+ ASSERT_EQ(completion_code, PLDM_ERROR_INVALID_DATA);
+ ASSERT_EQ(response->fru_data_major_version, 0x00);
+ ASSERT_EQ(response->fru_data_minor_version, 0x00);
+ ASSERT_EQ(response->fru_table_maximum_size, 0x00000000);
+ ASSERT_EQ(response->fru_table_length, 0x00000000);
+ ASSERT_EQ(response->total_record_set_identifiers, 0x0000);
+ ASSERT_EQ(response->total_table_records, 0x0000);
+ ASSERT_EQ(response->checksum, 0x00000000);
+}
+
+TEST(GetFruRecordTableMetadata, testBadEncodeResponse)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr) +
+ PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES>
+ responseMsg{};
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ uint8_t completion_code = PLDM_SUCCESS;
+ uint8_t fru_data_major_version = 0x12;
+ uint8_t fru_data_minor_version = 0x21;
+ uint32_t fru_table_maximum_size = 0x1234ABCD;
+ uint32_t fru_table_length = 0x56781234;
+ uint16_t total_record_set_identifiers = 0x34EF;
+ uint16_t total_table_records = 0xEEEF;
+ uint32_t checksum = 0x6543FA71;
+
+ auto rc = encode_get_fru_record_table_metadata_resp(
+ 0, completion_code, fru_data_major_version, fru_data_minor_version,
+ fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
+ total_table_records, checksum, NULL);
+
+ auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+ responsePtr->payload);
+
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ ASSERT_EQ(completion_code, PLDM_SUCCESS);
+ ASSERT_EQ(response->fru_data_major_version, 0x00);
+ ASSERT_EQ(response->fru_data_minor_version, 0x00);
+ ASSERT_EQ(response->fru_table_maximum_size, 0x00000000);
+ ASSERT_EQ(response->fru_table_length, 0x00000000);
+ ASSERT_EQ(response->total_record_set_identifiers, 0x0000);
+ ASSERT_EQ(response->total_table_records, 0x0000);
+ ASSERT_EQ(response->checksum, 0x00000000);
+}
+
+TEST(GetFruRecordTable, testGoodDecodeRequest)
+{
+ uint32_t data_transfer_handle = 31;
+ uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
+ std::array<uint8_t,
+ PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES + sizeof(pldm_msg_hdr)>
+ requestMsg{};
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ size_t payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
+ auto request =
+ reinterpret_cast<pldm_get_fru_record_table_req*>(requestPtr->payload);
+
+ request->data_transfer_handle = data_transfer_handle;
+ request->transfer_operation_flag = transfer_operation_flag;
+
+ uint32_t ret_data_transfer_handle = 0;
+ uint8_t ret_transfer_operation_flag = 0;
+
+ // Invoke decode get FRU record table request api
+ auto rc = decode_get_fru_record_table_req(requestPtr, payload_length,
+ &ret_data_transfer_handle,
+ &ret_transfer_operation_flag);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(data_transfer_handle, ret_data_transfer_handle);
+ ASSERT_EQ(transfer_operation_flag, ret_transfer_operation_flag);
+}
+
+TEST(GetFruRecordTable, testBadDecodeRequest)
+{
+ uint32_t data_transfer_handle = 0x0;
+ uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
+
+ std::array<uint8_t,
+ sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
+ requestMsg{};
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ // Payload message is missing
+ auto rc = decode_get_fru_record_table_req(NULL, 0, &data_transfer_handle,
+ &transfer_operation_flag);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // Payload length is invalid
+ rc = decode_get_fru_record_table_req(requestPtr, 0, &data_transfer_handle,
+ &transfer_operation_flag);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetFruRecordTable, testGoodEncodeResponse)
+{
+ uint8_t completion_code = 0;
+ uint32_t next_data_transfer_handle = 32;
+ uint8_t transfer_flag = PLDM_START_AND_END;
+
+ std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES);
+
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ auto response =
+ reinterpret_cast<pldm_get_fru_record_table_resp*>(responsePtr->payload);
+
+ // Invoke encode get FRU record table response api
+ auto rc = encode_get_fru_record_table_resp(0, completion_code,
+ next_data_transfer_handle,
+ transfer_flag, responsePtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
+ ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+ ASSERT_EQ(response->next_data_transfer_handle, next_data_transfer_handle);
+ ASSERT_EQ(response->transfer_flag, transfer_flag);
+}
+
+TEST(GetFruRecordTable, testBadEncodeResponse)
+{
+ uint32_t next_data_transfer_handle = 32;
+ uint8_t transfer_flag = PLDM_START_AND_END;
+
+ std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES);
+
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ auto rc = encode_get_fru_record_table_resp(
+ 0, PLDM_ERROR, next_data_transfer_handle, transfer_flag, responsePtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
+ ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
+
+ rc = encode_get_fru_record_table_resp(
+ 0, PLDM_SUCCESS, next_data_transfer_handle, transfer_flag, nullptr);
+
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
diff --git a/libpldm/tests/libpldm_pdr_test.cpp b/libpldm/tests/libpldm_pdr_test.cpp
new file mode 100644
index 0000000..c1caf20
--- /dev/null
+++ b/libpldm/tests/libpldm_pdr_test.cpp
@@ -0,0 +1,319 @@
+#include <array>
+
+#include "libpldm/pdr.h"
+#include "libpldm/platform.h"
+
+#include <gtest/gtest.h>
+
+TEST(PDRAccess, testInit)
+{
+ auto repo = pldm_pdr_init();
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 0);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), 0);
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRUpdate, testAdd)
+{
+ auto repo = pldm_pdr_init();
+
+ std::array<uint8_t, 10> data{};
+ auto handle = pldm_pdr_add(repo, data.data(), data.size(), 0);
+ EXPECT_EQ(handle, 1);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), data.size());
+
+ handle = pldm_pdr_add(repo, data.data(), data.size(), 0);
+ EXPECT_EQ(handle, 2);
+ handle = pldm_pdr_add(repo, data.data(), data.size(), 0);
+ EXPECT_EQ(handle, 3);
+ handle = pldm_pdr_add(repo, data.data(), data.size(), 0xdeeddeed);
+ EXPECT_EQ(handle, 0xdeeddeed);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), data.size() * 4);
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRAccess, testGet)
+{
+ auto repo = pldm_pdr_init();
+
+ std::array<uint32_t, 10> in{100, 345, 3, 6, 89, 0, 11, 45, 23434, 123123};
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in.data()), sizeof(in), 1);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in));
+ uint32_t size{};
+ uint32_t nextRecHdl{};
+ uint8_t* outData = nullptr;
+ auto hdl = pldm_pdr_find_record(repo, 0, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in));
+ EXPECT_EQ(nextRecHdl, 0);
+ EXPECT_EQ(memcmp(outData, in.data(), sizeof(in)), 0);
+ outData = nullptr;
+
+ auto hdl2 = pldm_pdr_find_record(repo, 1, &outData, &size, &nextRecHdl);
+ EXPECT_EQ(hdl, hdl2);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in));
+ EXPECT_EQ(nextRecHdl, 0);
+ EXPECT_EQ(memcmp(outData, in.data(), sizeof(in)), 0);
+ outData = nullptr;
+
+ hdl = pldm_pdr_find_record(repo, 0xdeaddead, &outData, &size, &nextRecHdl);
+ EXPECT_EQ(hdl, nullptr);
+ EXPECT_EQ(size, 0);
+ EXPECT_EQ(nextRecHdl, 0);
+ EXPECT_EQ(outData, nullptr);
+ outData = nullptr;
+
+ std::array<uint32_t, 10> in2{1000, 3450, 30, 60, 890,
+ 0, 110, 450, 234034, 123123};
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 2);
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 3);
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 4);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in2) * 4);
+ hdl = pldm_pdr_find_record(repo, 0, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in));
+ EXPECT_EQ(nextRecHdl, 2);
+ EXPECT_EQ(memcmp(outData, in.data(), sizeof(in)), 0);
+ outData = nullptr;
+ hdl2 = pldm_pdr_find_record(repo, 1, &outData, &size, &nextRecHdl);
+ EXPECT_EQ(hdl, hdl2);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in));
+ EXPECT_EQ(nextRecHdl, 2);
+ EXPECT_EQ(memcmp(outData, in.data(), sizeof(in)), 0);
+ outData = nullptr;
+ hdl = pldm_pdr_find_record(repo, 2, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in2));
+ EXPECT_EQ(nextRecHdl, 3);
+ EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
+ outData = nullptr;
+ hdl = pldm_pdr_find_record(repo, 3, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in2));
+ EXPECT_EQ(nextRecHdl, 4);
+ EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
+ outData = nullptr;
+ hdl = pldm_pdr_find_record(repo, 4, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in2));
+ EXPECT_EQ(nextRecHdl, 0);
+ EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
+ outData = nullptr;
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRAccess, testGetNext)
+{
+ auto repo = pldm_pdr_init();
+
+ std::array<uint32_t, 10> in{100, 345, 3, 6, 89, 0, 11, 45, 23434, 123123};
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in.data()), sizeof(in), 1);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in));
+ uint32_t size{};
+ uint32_t nextRecHdl{};
+ uint8_t* outData = nullptr;
+ auto hdl = pldm_pdr_find_record(repo, 0, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in));
+ EXPECT_EQ(nextRecHdl, 0);
+ EXPECT_EQ(memcmp(outData, in.data(), sizeof(in)), 0);
+ outData = nullptr;
+
+ std::array<uint32_t, 10> in2{1000, 3450, 30, 60, 890,
+ 0, 110, 450, 234034, 123123};
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 2);
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 3);
+ pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 4);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in2) * 4);
+ hdl = pldm_pdr_get_next_record(repo, hdl, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in2));
+ EXPECT_EQ(nextRecHdl, 3);
+ EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
+ outData = nullptr;
+ hdl = pldm_pdr_get_next_record(repo, hdl, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in2));
+ EXPECT_EQ(nextRecHdl, 4);
+ EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
+ outData = nullptr;
+ hdl = pldm_pdr_get_next_record(repo, hdl, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(in2));
+ EXPECT_EQ(nextRecHdl, 0);
+ EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
+ outData = nullptr;
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRAccess, testFindByType)
+{
+ auto repo = pldm_pdr_init();
+
+ std::array<uint8_t, sizeof(pldm_pdr_hdr)> data{};
+ pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(data.data());
+ hdr->type = 1;
+ auto first = pldm_pdr_add(repo, data.data(), data.size(), 0);
+ hdr->type = 2;
+ auto second = pldm_pdr_add(repo, data.data(), data.size(), 0);
+ hdr->type = 3;
+ auto third = pldm_pdr_add(repo, data.data(), data.size(), 0);
+ hdr->type = 4;
+ auto fourth = pldm_pdr_add(repo, data.data(), data.size(), 0);
+
+ uint8_t* outData = nullptr;
+ uint32_t size{};
+ auto firstRec =
+ pldm_pdr_find_record_by_type(repo, 1, nullptr, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, firstRec), first);
+ outData = nullptr;
+ auto secondRec =
+ pldm_pdr_find_record_by_type(repo, 2, nullptr, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, secondRec), second);
+ outData = nullptr;
+ auto thirdRec =
+ pldm_pdr_find_record_by_type(repo, 3, nullptr, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, thirdRec), third);
+ outData = nullptr;
+ auto fourthRec =
+ pldm_pdr_find_record_by_type(repo, 4, nullptr, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, fourthRec), fourth);
+ outData = nullptr;
+ auto fifthRec =
+ pldm_pdr_find_record_by_type(repo, 5, nullptr, &outData, &size);
+ EXPECT_EQ(fifthRec, nullptr);
+ EXPECT_EQ(outData, nullptr);
+ EXPECT_EQ(size, 0);
+
+ auto rec =
+ pldm_pdr_find_record_by_type(repo, 3, secondRec, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, rec), third);
+ outData = nullptr;
+ rec = pldm_pdr_find_record_by_type(repo, 4, secondRec, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, rec), fourth);
+ outData = nullptr;
+ rec = pldm_pdr_find_record_by_type(repo, 2, firstRec, &outData, &size);
+ EXPECT_EQ(pldm_pdr_get_record_handle(repo, rec), second);
+ outData = nullptr;
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRUpdate, testAddFruRecordSet)
+{
+ auto repo = pldm_pdr_init();
+
+ auto handle = pldm_pdr_add_fru_record_set(repo, 1, 10, 1, 0, 100);
+ EXPECT_EQ(handle, 1);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo),
+ sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ uint32_t size{};
+ uint32_t nextRecHdl{};
+ uint8_t* outData = nullptr;
+ auto hdl = pldm_pdr_find_record(repo, 0, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(nextRecHdl, 0);
+ pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(outData);
+ EXPECT_EQ(hdr->version, 1);
+ EXPECT_EQ(hdr->type, PLDM_PDR_FRU_RECORD_SET);
+ EXPECT_EQ(hdr->length, sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(hdr->record_handle, 1);
+ pldm_pdr_fru_record_set* fru = reinterpret_cast<pldm_pdr_fru_record_set*>(
+ outData + sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(fru->terminus_handle, 1);
+ EXPECT_EQ(fru->fru_rsi, 10);
+ EXPECT_EQ(fru->entity_type, 1);
+ EXPECT_EQ(fru->entity_instance_num, 0);
+ EXPECT_EQ(fru->container_id, 100);
+ outData = nullptr;
+
+ handle = pldm_pdr_add_fru_record_set(repo, 2, 11, 2, 1, 101);
+ EXPECT_EQ(handle, 2);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ EXPECT_EQ(pldm_pdr_get_repo_size(repo),
+ 2 * (sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set)));
+ hdl = pldm_pdr_find_record(repo, 2, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(nextRecHdl, 0);
+ hdr = reinterpret_cast<pldm_pdr_hdr*>(outData);
+ EXPECT_EQ(hdr->version, 1);
+ EXPECT_EQ(hdr->type, PLDM_PDR_FRU_RECORD_SET);
+ EXPECT_EQ(hdr->length, sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(hdr->record_handle, 2);
+ fru = reinterpret_cast<pldm_pdr_fru_record_set*>(outData +
+ sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(fru->terminus_handle, 2);
+ EXPECT_EQ(fru->fru_rsi, 11);
+ EXPECT_EQ(fru->entity_type, 2);
+ EXPECT_EQ(fru->entity_instance_num, 1);
+ EXPECT_EQ(fru->container_id, 101);
+ outData = nullptr;
+
+ hdl = pldm_pdr_find_record(repo, 1, &outData, &size, &nextRecHdl);
+ EXPECT_NE(hdl, nullptr);
+ EXPECT_EQ(size, sizeof(pldm_pdr_hdr) + sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(nextRecHdl, 2);
+ hdr = reinterpret_cast<pldm_pdr_hdr*>(outData);
+ EXPECT_EQ(hdr->version, 1);
+ EXPECT_EQ(hdr->type, PLDM_PDR_FRU_RECORD_SET);
+ EXPECT_EQ(hdr->length, sizeof(pldm_pdr_fru_record_set));
+ EXPECT_EQ(hdr->record_handle, 1);
+ fru = reinterpret_cast<pldm_pdr_fru_record_set*>(outData +
+ sizeof(pldm_pdr_hdr));
+ EXPECT_EQ(fru->terminus_handle, 1);
+ EXPECT_EQ(fru->fru_rsi, 10);
+ EXPECT_EQ(fru->entity_type, 1);
+ EXPECT_EQ(fru->entity_instance_num, 0);
+ EXPECT_EQ(fru->container_id, 100);
+ outData = nullptr;
+
+ pldm_pdr_destroy(repo);
+}
+
+TEST(PDRUpdate, tesFindtFruRecordSet)
+{
+ auto repo = pldm_pdr_init();
+
+ uint16_t terminusHdl{};
+ uint16_t entityType{};
+ uint16_t entityInstanceNum{};
+ uint16_t containerId{};
+ auto first = pldm_pdr_add_fru_record_set(repo, 1, 1, 1, 0, 100);
+ auto second = pldm_pdr_add_fru_record_set(repo, 1, 2, 1, 1, 100);
+ auto third = pldm_pdr_add_fru_record_set(repo, 1, 3, 1, 2, 100);
+ EXPECT_EQ(first, pldm_pdr_get_record_handle(
+ repo, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 1, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId)));
+ EXPECT_EQ(second, pldm_pdr_get_record_handle(
+ repo, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 2, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId)));
+ EXPECT_EQ(third, pldm_pdr_get_record_handle(
+ repo, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 3, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId)));
+ EXPECT_EQ(terminusHdl, 1);
+ EXPECT_EQ(entityType, 1);
+ EXPECT_EQ(entityInstanceNum, 2);
+ EXPECT_EQ(containerId, 100);
+ EXPECT_EQ(nullptr, pldm_pdr_fru_record_set_find_by_rsi(
+ repo, 4, &terminusHdl, &entityType,
+ &entityInstanceNum, &containerId));
+
+ pldm_pdr_destroy(repo);
+}
diff --git a/libpldm/tests/libpldm_platform_test.cpp b/libpldm/tests/libpldm_platform_test.cpp
new file mode 100644
index 0000000..11252d6
--- /dev/null
+++ b/libpldm/tests/libpldm_platform_test.cpp
@@ -0,0 +1,545 @@
+#include <string.h>
+
+#include <array>
+
+#include "libpldm/base.h"
+#include "libpldm/platform.h"
+
+#include <gtest/gtest.h>
+
+constexpr auto hdrSize = sizeof(pldm_msg_hdr);
+
+TEST(SetStateEffecterStates, testEncodeResponse)
+{
+ std::array<uint8_t,
+ sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ uint8_t completionCode = 0;
+
+ auto rc = encode_set_state_effecter_states_resp(0, PLDM_SUCCESS, response);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, response->payload[0]);
+}
+
+TEST(SetStateEffecterStates, testEncodeRequest)
+{
+ std::array<uint8_t,
+ sizeof(pldm_msg_hdr) + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ uint16_t effecterId = 0x0A;
+ uint8_t compEffecterCnt = 0x2;
+ std::array<set_effecter_state_field, 8> stateField{};
+ stateField[0] = {PLDM_REQUEST_SET, 2};
+ stateField[1] = {PLDM_REQUEST_SET, 3};
+
+ auto rc = encode_set_state_effecter_states_req(
+ 0, effecterId, compEffecterCnt, stateField.data(), request);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(effecterId, request->payload[0]);
+ EXPECT_EQ(compEffecterCnt, request->payload[sizeof(effecterId)]);
+ EXPECT_EQ(stateField[0].set_request,
+ request->payload[sizeof(effecterId) + sizeof(compEffecterCnt)]);
+ EXPECT_EQ(stateField[0].effecter_state,
+ request->payload[sizeof(effecterId) + sizeof(compEffecterCnt) +
+ sizeof(stateField[0].set_request)]);
+ EXPECT_EQ(stateField[1].set_request,
+ request->payload[sizeof(effecterId) + sizeof(compEffecterCnt) +
+ sizeof(stateField[0])]);
+ EXPECT_EQ(stateField[1].effecter_state,
+ request->payload[sizeof(effecterId) + sizeof(compEffecterCnt) +
+ sizeof(stateField[0]) +
+ sizeof(stateField[1].set_request)]);
+}
+
+TEST(SetStateEffecterStates, testGoodDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES>
+ responseMsg{};
+
+ uint8_t retcompletion_code = 0;
+
+ responseMsg[hdrSize] = PLDM_SUCCESS;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_set_state_effecter_states_resp(
+ response, responseMsg.size() - hdrSize, &retcompletion_code);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(PLDM_SUCCESS, retcompletion_code);
+}
+
+TEST(SetStateEffecterStates, testGoodDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES>
+ requestMsg{};
+
+ uint16_t effecterId = 0x32;
+ uint8_t compEffecterCnt = 0x2;
+
+ std::array<set_effecter_state_field, 8> stateField{};
+ stateField[0] = {PLDM_REQUEST_SET, 3};
+ stateField[1] = {PLDM_REQUEST_SET, 4};
+
+ uint16_t retEffecterId = 0;
+ uint8_t retCompEffecterCnt = 0;
+
+ std::array<set_effecter_state_field, 8> retStateField{};
+
+ memcpy(requestMsg.data() + hdrSize, &effecterId, sizeof(effecterId));
+ memcpy(requestMsg.data() + sizeof(effecterId) + hdrSize, &compEffecterCnt,
+ sizeof(compEffecterCnt));
+ memcpy(requestMsg.data() + sizeof(effecterId) + sizeof(compEffecterCnt) +
+ hdrSize,
+ &stateField, sizeof(stateField));
+
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = decode_set_state_effecter_states_req(
+ request, requestMsg.size() - hdrSize, &retEffecterId,
+ &retCompEffecterCnt, retStateField.data());
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(effecterId, retEffecterId);
+ EXPECT_EQ(retCompEffecterCnt, compEffecterCnt);
+ EXPECT_EQ(retStateField[0].set_request, stateField[0].set_request);
+ EXPECT_EQ(retStateField[0].effecter_state, stateField[0].effecter_state);
+ EXPECT_EQ(retStateField[1].set_request, stateField[1].set_request);
+ EXPECT_EQ(retStateField[1].effecter_state, stateField[1].effecter_state);
+}
+
+TEST(SetStateEffecterStates, testBadDecodeRequest)
+{
+ const struct pldm_msg* msg = NULL;
+
+ auto rc = decode_set_state_effecter_states_req(msg, sizeof(*msg), NULL,
+ NULL, NULL);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(SetStateEffecterStates, testBadDecodeResponse)
+{
+ std::array<uint8_t, PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES>
+ responseMsg{};
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_set_state_effecter_states_resp(response,
+ responseMsg.size(), NULL);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetPDR, testGoodEncodeResponse)
+{
+ uint8_t completionCode = 0;
+ uint32_t nextRecordHndl = 0x12;
+ uint32_t nextDataTransferHndl = 0x13;
+ uint8_t transferFlag = PLDM_END;
+ uint16_t respCnt = 0x5;
+ std::vector<uint8_t> recordData{1, 2, 3, 4, 5};
+ uint8_t transferCRC = 6;
+
+ // + size of record data and transfer CRC
+ std::vector<uint8_t> responseMsg(hdrSize + PLDM_GET_PDR_MIN_RESP_BYTES +
+ recordData.size() + 1);
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = encode_get_pdr_resp(0, PLDM_SUCCESS, nextRecordHndl,
+ nextDataTransferHndl, transferFlag, respCnt,
+ recordData.data(), transferCRC, response);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ struct pldm_get_pdr_resp* resp =
+ reinterpret_cast<struct pldm_get_pdr_resp*>(response->payload);
+
+ EXPECT_EQ(completionCode, resp->completion_code);
+ EXPECT_EQ(nextRecordHndl, resp->next_record_handle);
+ EXPECT_EQ(nextDataTransferHndl, resp->next_data_transfer_handle);
+ EXPECT_EQ(transferFlag, resp->transfer_flag);
+ EXPECT_EQ(respCnt, resp->response_count);
+ EXPECT_EQ(0,
+ memcmp(recordData.data(), resp->record_data, recordData.size()));
+ EXPECT_EQ(*(response->payload + sizeof(pldm_get_pdr_resp) - 1 +
+ recordData.size()),
+ transferCRC);
+
+ transferFlag = PLDM_START_AND_END; // No CRC in this case
+ responseMsg.resize(responseMsg.size() - sizeof(transferCRC));
+ rc = encode_get_pdr_resp(0, PLDM_SUCCESS, nextRecordHndl,
+ nextDataTransferHndl, transferFlag, respCnt,
+ recordData.data(), transferCRC, response);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+}
+
+TEST(GetPDR, testBadEncodeResponse)
+{
+ uint32_t nextRecordHndl = 0x12;
+ uint32_t nextDataTransferHndl = 0x13;
+ uint8_t transferFlag = PLDM_START_AND_END;
+ uint16_t respCnt = 0x5;
+ std::vector<uint8_t> recordData{1, 2, 3, 4, 5};
+ uint8_t transferCRC = 0;
+
+ auto rc = encode_get_pdr_resp(0, PLDM_SUCCESS, nextRecordHndl,
+ nextDataTransferHndl, transferFlag, respCnt,
+ recordData.data(), transferCRC, nullptr);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetPDR, testGoodDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_GET_PDR_REQ_BYTES> requestMsg{};
+
+ uint32_t recordHndl = 0x32;
+ uint32_t dataTransferHndl = 0x11;
+ uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+ uint16_t requestCnt = 0x5;
+ uint16_t recordChangeNum = 0;
+
+ uint32_t retRecordHndl = 0;
+ uint32_t retDataTransferHndl = 0;
+ uint8_t retTransferOpFlag = 0;
+ uint16_t retRequestCnt = 0;
+ uint16_t retRecordChangeNum = 0;
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_get_pdr_req* request =
+ reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
+
+ request->record_handle = recordHndl;
+ request->data_transfer_handle = dataTransferHndl;
+ request->transfer_op_flag = transferOpFlag;
+ request->request_count = requestCnt;
+ request->record_change_number = recordChangeNum;
+
+ auto rc = decode_get_pdr_req(
+ req, requestMsg.size() - hdrSize, &retRecordHndl, &retDataTransferHndl,
+ &retTransferOpFlag, &retRequestCnt, &retRecordChangeNum);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retRecordHndl, recordHndl);
+ EXPECT_EQ(retDataTransferHndl, dataTransferHndl);
+ EXPECT_EQ(retTransferOpFlag, transferOpFlag);
+ EXPECT_EQ(retRequestCnt, requestCnt);
+ EXPECT_EQ(retRecordChangeNum, recordChangeNum);
+}
+
+TEST(GetPDR, testBadDecodeRequest)
+{
+ std::array<uint8_t, PLDM_GET_PDR_REQ_BYTES> requestMsg{};
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = decode_get_pdr_req(req, requestMsg.size(), NULL, NULL, NULL, NULL,
+ NULL);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetPDR, testGoodEncodeRequest)
+{
+ uint32_t record_hndl = 0;
+ uint32_t data_transfer_hndl = 0;
+ uint8_t transfer_op_flag = PLDM_GET_FIRSTPART;
+ uint16_t request_cnt = 20;
+ uint16_t record_chg_num = 0;
+
+ std::vector<uint8_t> requestMsg(hdrSize + PLDM_GET_PDR_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_pdr_req(0, record_hndl, data_transfer_hndl,
+ transfer_op_flag, request_cnt, record_chg_num,
+ request, PLDM_GET_PDR_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ struct pldm_get_pdr_req* req =
+ reinterpret_cast<struct pldm_get_pdr_req*>(request->payload);
+ EXPECT_EQ(record_hndl, req->record_handle);
+ EXPECT_EQ(data_transfer_hndl, req->data_transfer_handle);
+ EXPECT_EQ(transfer_op_flag, req->transfer_op_flag);
+ EXPECT_EQ(request_cnt, req->request_count);
+ EXPECT_EQ(record_chg_num, req->record_change_number);
+}
+
+TEST(GetPDR, testBadEncodeRequest)
+{
+ uint32_t record_hndl = 0;
+ uint32_t data_transfer_hndl = 0;
+ uint8_t transfer_op_flag = PLDM_GET_FIRSTPART;
+ uint16_t request_cnt = 32;
+ uint16_t record_chg_num = 0;
+
+ std::vector<uint8_t> requestMsg(hdrSize + PLDM_GET_PDR_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_get_pdr_req(0, record_hndl, data_transfer_hndl,
+ transfer_op_flag, request_cnt, record_chg_num,
+ nullptr, PLDM_GET_PDR_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = encode_get_pdr_req(0, record_hndl, data_transfer_hndl,
+ transfer_op_flag, request_cnt, record_chg_num,
+ request, PLDM_GET_PDR_REQ_BYTES + 1);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetPDR, testGoodDecodeResponse)
+{
+ const char* recordData = "123456789";
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint32_t nextRecordHndl = 0;
+ uint32_t nextDataTransferHndl = 0;
+ uint8_t transferFlag = PLDM_END;
+ constexpr uint16_t respCnt = 9;
+ uint8_t transferCRC = 96;
+ size_t recordDataLength = 32;
+ std::array<uint8_t, hdrSize + PLDM_GET_PDR_MIN_RESP_BYTES + respCnt +
+ sizeof(transferCRC)>
+ responseMsg{};
+
+ uint8_t retCompletionCode = 0;
+ uint8_t retRecordData[32] = {0};
+ uint32_t retNextRecordHndl = 0;
+ uint32_t retNextDataTransferHndl = 0;
+ uint8_t retTransferFlag = 0;
+ uint16_t retRespCnt = 0;
+ uint8_t retTransferCRC = 0;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ struct pldm_get_pdr_resp* resp =
+ reinterpret_cast<struct pldm_get_pdr_resp*>(response->payload);
+ resp->completion_code = completionCode;
+ resp->next_record_handle = htole32(nextRecordHndl);
+ resp->next_data_transfer_handle = htole32(nextDataTransferHndl);
+ resp->transfer_flag = transferFlag;
+ resp->response_count = htole16(respCnt);
+ memcpy(resp->record_data, recordData, respCnt);
+ response->payload[PLDM_GET_PDR_MIN_RESP_BYTES + respCnt] = transferCRC;
+
+ auto rc = decode_get_pdr_resp(
+ response, responseMsg.size() - hdrSize, &retCompletionCode,
+ &retNextRecordHndl, &retNextDataTransferHndl, &retTransferFlag,
+ &retRespCnt, retRecordData, recordDataLength, &retTransferCRC);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retCompletionCode, completionCode);
+ EXPECT_EQ(retNextRecordHndl, nextRecordHndl);
+ EXPECT_EQ(retNextDataTransferHndl, nextDataTransferHndl);
+ EXPECT_EQ(retTransferFlag, transferFlag);
+ EXPECT_EQ(retRespCnt, respCnt);
+ EXPECT_EQ(retTransferCRC, transferCRC);
+ EXPECT_EQ(0, memcmp(recordData, resp->record_data, respCnt));
+}
+
+TEST(GetPDR, testBadDecodeResponse)
+{
+ const char* recordData = "123456789";
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint32_t nextRecordHndl = 0;
+ uint32_t nextDataTransferHndl = 0;
+ uint8_t transferFlag = PLDM_END;
+ constexpr uint16_t respCnt = 9;
+ uint8_t transferCRC = 96;
+ size_t recordDataLength = 32;
+ std::array<uint8_t, hdrSize + PLDM_GET_PDR_MIN_RESP_BYTES + respCnt +
+ sizeof(transferCRC)>
+ responseMsg{};
+
+ uint8_t retCompletionCode = 0;
+ uint8_t retRecordData[32] = {0};
+ uint32_t retNextRecordHndl = 0;
+ uint32_t retNextDataTransferHndl = 0;
+ uint8_t retTransferFlag = 0;
+ uint16_t retRespCnt = 0;
+ uint8_t retTransferCRC = 0;
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ struct pldm_get_pdr_resp* resp =
+ reinterpret_cast<struct pldm_get_pdr_resp*>(response->payload);
+ resp->completion_code = completionCode;
+ resp->next_record_handle = htole32(nextRecordHndl);
+ resp->next_data_transfer_handle = htole32(nextDataTransferHndl);
+ resp->transfer_flag = transferFlag;
+ resp->response_count = htole16(respCnt);
+ memcpy(resp->record_data, recordData, respCnt);
+ response->payload[PLDM_GET_PDR_MIN_RESP_BYTES + respCnt] = transferCRC;
+
+ auto rc = decode_get_pdr_resp(response, responseMsg.size() - hdrSize, NULL,
+ NULL, NULL, NULL, NULL, NULL, 0, NULL);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_pdr_resp(
+ response, responseMsg.size() - hdrSize - 1, &retCompletionCode,
+ &retNextRecordHndl, &retNextDataTransferHndl, &retTransferFlag,
+ &retRespCnt, retRecordData, recordDataLength, &retTransferCRC);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetNumericEffecterValue, testGoodDecodeRequest)
+{
+ std::array<uint8_t,
+ hdrSize + PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES + 3>
+ requestMsg{};
+
+ uint16_t effecter_id = 32768;
+ uint8_t effecter_data_size = PLDM_EFFECTER_DATA_SIZE_UINT32;
+ uint32_t effecter_value = 123456789;
+
+ uint16_t reteffecter_id;
+ uint8_t reteffecter_data_size;
+ uint8_t reteffecter_value[4];
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_set_numeric_effecter_value_req* request =
+ reinterpret_cast<struct pldm_set_numeric_effecter_value_req*>(
+ req->payload);
+
+ request->effecter_id = effecter_id;
+ request->effecter_data_size = effecter_data_size;
+ memcpy(request->effecter_value, &effecter_value, sizeof(effecter_value));
+
+ auto rc = decode_set_numeric_effecter_value_req(
+ req, requestMsg.size() - hdrSize, &reteffecter_id,
+ &reteffecter_data_size, reinterpret_cast<uint8_t*>(&reteffecter_value));
+
+ uint32_t value = *(reinterpret_cast<uint32_t*>(&reteffecter_value[0]));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(reteffecter_id, effecter_id);
+ EXPECT_EQ(reteffecter_data_size, effecter_data_size);
+ EXPECT_EQ(value, effecter_value);
+}
+
+TEST(SetNumericEffecterValue, testBadDecodeRequest)
+{
+ std::array<uint8_t, hdrSize + PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES>
+ requestMsg{};
+
+ auto rc = decode_set_numeric_effecter_value_req(
+ NULL, requestMsg.size() - hdrSize, NULL, NULL, NULL);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ uint16_t effecter_id = 0x10;
+ uint8_t effecter_data_size = PLDM_EFFECTER_DATA_SIZE_UINT8;
+ uint8_t effecter_value = 1;
+
+ uint16_t reteffecter_id;
+ uint8_t reteffecter_data_size;
+ uint8_t reteffecter_value[4];
+
+ auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ struct pldm_set_numeric_effecter_value_req* request =
+ reinterpret_cast<struct pldm_set_numeric_effecter_value_req*>(
+ req->payload);
+
+ request->effecter_id = effecter_id;
+ request->effecter_data_size = effecter_data_size;
+ memcpy(request->effecter_value, &effecter_value, sizeof(effecter_value));
+
+ rc = decode_set_numeric_effecter_value_req(
+ req, requestMsg.size() - hdrSize - 1, &reteffecter_id,
+ &reteffecter_data_size, reinterpret_cast<uint8_t*>(&reteffecter_value));
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetNumericEffecterValue, testGoodEncodeRequest)
+{
+ uint16_t effecter_id = 0;
+ uint8_t effecter_data_size = PLDM_EFFECTER_DATA_SIZE_UINT8;
+ uint8_t effecter_value = 1;
+
+ std::vector<uint8_t> requestMsg(
+ hdrSize + PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_set_numeric_effecter_value_req(
+ 0, effecter_id, effecter_data_size,
+ reinterpret_cast<uint8_t*>(&effecter_value), request,
+ PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ struct pldm_set_numeric_effecter_value_req* req =
+ reinterpret_cast<struct pldm_set_numeric_effecter_value_req*>(
+ request->payload);
+ EXPECT_EQ(effecter_id, req->effecter_id);
+ EXPECT_EQ(effecter_data_size, req->effecter_data_size);
+ EXPECT_EQ(effecter_value,
+ *(reinterpret_cast<uint8_t*>(&req->effecter_value[0])));
+}
+
+TEST(SetNumericEffecterValue, testBadEncodeRequest)
+{
+ std::vector<uint8_t> requestMsg(
+ hdrSize + PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = encode_set_numeric_effecter_value_req(
+ 0, 0, 0, NULL, NULL, PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ uint16_t effecter_value;
+ rc = encode_set_numeric_effecter_value_req(
+ 0, 0, 6, reinterpret_cast<uint8_t*>(&effecter_value), request,
+ PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(SetNumericEffecterValue, testGoodDecodeResponse)
+{
+ std::array<uint8_t, hdrSize + PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES>
+ responseMsg{};
+
+ uint8_t completion_code = 0xA0;
+
+ uint8_t retcompletion_code;
+
+ memcpy(responseMsg.data() + hdrSize, &completion_code,
+ sizeof(completion_code));
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_set_numeric_effecter_value_resp(
+ response, responseMsg.size() - hdrSize, &retcompletion_code);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completion_code, retcompletion_code);
+}
+
+TEST(SetNumericEffecterValue, testBadDecodeResponse)
+{
+ std::array<uint8_t, PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES>
+ responseMsg{};
+
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ auto rc = decode_set_numeric_effecter_value_resp(response,
+ responseMsg.size(), NULL);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(SetNumericEffecterValue, testGoodEncodeResponse)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr) +
+ PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES>
+ responseMsg{};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ uint8_t completionCode = 0;
+
+ auto rc = encode_set_numeric_effecter_value_resp(
+ 0, PLDM_SUCCESS, response, PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(completionCode, response->payload[0]);
+}
+
+TEST(SetNumericEffecterValue, testBadEncodeResponse)
+{
+ auto rc = encode_set_numeric_effecter_value_resp(
+ 0, PLDM_SUCCESS, NULL, PLDM_SET_NUMERIC_EFFECTER_VALUE_RESP_BYTES);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
diff --git a/libpldm/tests/libpldm_utils_test.cpp b/libpldm/tests/libpldm_utils_test.cpp
new file mode 100644
index 0000000..990a62b
--- /dev/null
+++ b/libpldm/tests/libpldm_utils_test.cpp
@@ -0,0 +1,90 @@
+#include <cstring>
+#include <vector>
+
+#include "libpldm/utils.h"
+
+#include <gtest/gtest.h>
+
+TEST(Crc32, CheckSumTest)
+{
+ const char* password = "123456789";
+ auto checksum = crc32(password, 9);
+ EXPECT_EQ(checksum, 0xcbf43926);
+}
+
+TEST(Crc8, CheckSumTest)
+{
+ const char* data = "123456789";
+ auto checksum = crc8(data, 9);
+ EXPECT_EQ(checksum, 0xf4);
+}
+
+TEST(Ver2string, Ver2string)
+{
+ ver32_t version{0xf3, 0xf7, 0x10, 0x61};
+ const char* vstr = "3.7.10a";
+ char buffer[1024];
+ auto rc = ver2str(&version, buffer, sizeof(buffer));
+ EXPECT_EQ(rc, std::strlen(vstr));
+ EXPECT_STREQ(vstr, buffer);
+
+ version = {0x10, 0x01, 0xf7, 0x00};
+ vstr = "10.01.7";
+ rc = ver2str(&version, buffer, sizeof(buffer));
+ EXPECT_EQ(rc, std::strlen(vstr));
+ EXPECT_STREQ(vstr, buffer);
+
+ version = {0xf3, 0xf1, 0xff, 0x00};
+ vstr = "3.1";
+ rc = ver2str(&version, buffer, sizeof(buffer));
+ EXPECT_EQ(rc, std::strlen(vstr));
+ EXPECT_STREQ(vstr, buffer);
+
+ version = {0xf1, 0xf0, 0xff, 0x61};
+ vstr = "1.0a";
+ rc = ver2str(&version, buffer, sizeof(buffer));
+ EXPECT_EQ(rc, std::strlen(vstr));
+ EXPECT_STREQ(vstr, buffer);
+
+ rc = ver2str(&version, buffer, 3);
+ EXPECT_EQ(rc, 2);
+ EXPECT_STREQ("1.", buffer);
+
+ rc = ver2str(&version, buffer, 1);
+ EXPECT_EQ(rc, 0);
+
+ rc = ver2str(&version, buffer, 0);
+ EXPECT_EQ(rc, -1);
+}
+
+TEST(BcdConversion, BcdCoversion)
+{
+ EXPECT_EQ(12, bcd2dec8(0x12));
+ EXPECT_EQ(99, bcd2dec8(0x99));
+ EXPECT_EQ(1234, bcd2dec16(0x1234));
+ EXPECT_EQ(9999, bcd2dec16(0x9999));
+ EXPECT_EQ(12345678, bcd2dec32(0x12345678));
+ EXPECT_EQ(99999999, bcd2dec32(0x99999999));
+
+ EXPECT_EQ(0x12, dec2bcd8(12));
+ EXPECT_EQ(0x99, dec2bcd8(99));
+ EXPECT_EQ(0x1234, dec2bcd16(1234));
+ EXPECT_EQ(0x9999, dec2bcd16(9999));
+ EXPECT_EQ(0x12345678, dec2bcd32(12345678));
+ EXPECT_EQ(0x99999999, dec2bcd32(99999999));
+}
+
+TEST(TimeLegal, TimeLegal)
+{
+ EXPECT_EQ(true, is_time_legal(30, 25, 16, 18, 8, 2019));
+ EXPECT_EQ(true, is_time_legal(30, 25, 16, 29, 2, 2020)); // leap year
+
+ EXPECT_EQ(false, is_time_legal(30, 25, 16, 18, 8, 1960)); // year illegal
+ EXPECT_EQ(false, is_time_legal(30, 25, 16, 18, 15, 2019)); // month illegal
+ EXPECT_EQ(false, is_time_legal(30, 25, 16, 18, 0, 2019)); // month illegal
+ EXPECT_EQ(false, is_time_legal(30, 25, 16, 0, 8, 2019)); // day illegal
+ EXPECT_EQ(false, is_time_legal(30, 25, 16, 29, 2, 2019)); // day illegal
+ EXPECT_EQ(false, is_time_legal(30, 25, 25, 18, 8, 2019)); // hours illegal
+ EXPECT_EQ(false, is_time_legal(30, 70, 16, 18, 8, 2019)); // minutes illegal
+ EXPECT_EQ(false, is_time_legal(80, 25, 16, 18, 8, 2019)); // seconds illegal
+}
\ No newline at end of file
diff --git a/libpldm/tests/meson.build b/libpldm/tests/meson.build
new file mode 100644
index 0000000..08d2d19
--- /dev/null
+++ b/libpldm/tests/meson.build
@@ -0,0 +1,45 @@
+if get_option('oe-sdk').enabled()
+ # Setup OE SYSROOT
+ OECORE_TARGET_SYSROOT = run_command('sh', '-c', 'echo $OECORE_TARGET_SYSROOT').stdout().strip()
+ if OECORE_TARGET_SYSROOT == ''
+ error('Unable to get $OECORE_TARGET_SYSROOT, check your environment.')
+ endif
+ message('OE_SYSROOT: ' + OECORE_TARGET_SYSROOT)
+ rpath = ':'.join([OECORE_TARGET_SYSROOT + '/lib', OECORE_TARGET_SYSROOT + '/usr/lib'])
+ ld_so = run_command('sh', '-c', 'find ' + OECORE_TARGET_SYSROOT + '/lib/ld-*.so | sort -r -n | head -n1').stdout().strip()
+ dynamic_linker = ['-Wl,-dynamic-linker,' + ld_so]
+else
+ dynamic_linker = []
+endif
+
+gtest = dependency('gtest', main: true, disabler: true, required: true)
+gmock = dependency('gmock', disabler: true, required: true)
+
+tests = [
+ 'libpldm_base_test',
+ 'libpldm_platform_test',
+ 'libpldm_bios_test',
+ 'libpldm_bios_table_test',
+ 'libpldm_fru_test',
+ 'libpldm_utils_test',
+ 'libpldm_pdr_test'
+]
+
+if get_option('oem-ibm').enabled()
+ tests += [
+ '../../oem/ibm/test/libpldm_fileio_test',
+ ]
+endif
+
+foreach t : tests
+ test(t, executable(t.underscorify(), t + '.cpp',
+ implicit_include_directories: false,
+ link_args: dynamic_linker,
+ build_rpath: get_option('oe-sdk').enabled() ? rpath : '',
+ dependencies: [
+ libpldm,
+ gtest,
+ gmock]),
+ workdir: meson.current_source_dir())
+endforeach
+