| From 016f55dfaf07c3b90bdc8ef0318629751f1a3b6e Mon Sep 17 00:00:00 2001 |
| From: Nikhil Namjoshi <nikhilnamjoshi@google.com> |
| Date: Thu, 7 Dec 2023 00:05:33 +0000 |
| Subject: [PATCH] Adding RDEOperationEnumerate support |
| |
| Add encoders and decoders for RDEOperationEnumerate. |
| Additionlly added code hooks to serve RDEOperationEnumerate |
| requests from the client. Also added test for the encoders |
| and decoders. |
| |
| Tested: |
| Unit tested the encoders and decoders |
| Additionally tested the fix through libmctp app by sending |
| RdeOperationEnumerate requested in the middle of the |
| RdeOperationComplete request |
| |
| ``` |
| 0xc0000 |
| Reading 0xc0000 |
| |
| Received. EID: 9 tag_owner: 0 msg_tag: 6 len:265 |
| cc: 0 |
| operation_status: 5 |
| completion_percentage: 100 |
| Has paylaod: Yes |
| response_payload_length: 242 |
| etag len: 1 |
| etag: |
| {"@odata.id":"/redfish/v1/Chassis/Tray/Controls","@odata.type":"#ControlCollection.ControlCollection","Name":"Control Collection","Members":[{"@odata.id":"/redfish/v1/Chassis/Tray/Controls/HDD_pid"},{"@odata.id":"/redfish/v1/Chassis/Tray/Controls/fans"}],"Members@odata.count":2} |
| |
| { |
| "@odata.id": "/redfish/v1/Chassis/Tray/Controls", |
| "@odata.type": "#ControlCollection.ControlCollection", |
| "Members": [ |
| { |
| "@odata.id": "/redfish/v1/Chassis/Tray/Controls/HDD_pid" |
| }, |
| { |
| "@odata.id": "/redfish/v1/Chassis/Tray/Controls/fans" |
| } |
| ], |
| "Members@odata.count": 2, |
| "Name": "Control Collection" |
| } |
| |
| Received. EID: 9 tag_owner: 0 msg_tag: 6 len:13 |
| cc: 0 |
| operation count : 1 |
| Resource Id : 786432 |
| Operation Id: 65451 |
| Operation Type : 1 |
| Resource id verified |
| |
| Received. EID: 9 tag_owner: 0 msg_tag: 6 len:4 |
| cc: 0 |
| operation completed!!! |
| ``` |
| |
| Patch Tracking Bug: b/323193207 |
| Upstream info / review: NA |
| Upstream-Status: Pending |
| Justification: |
| There is dependency on upstreaming rded first, followed |
| by other libpldm command support like OperationInit, |
| Operation,Status, OperationComplete and OperationKill |
| |
| Change-Id: Ifda68fc89837d746a360bc7e56e932c79db6a9e8 |
| Signed-off-by: Nikhil Namjoshi <nikhilnamjoshi@google.com> |
| --- |
| include/libpldm/pldm_rde.h | 92 ++++++++++++- |
| src/pldm_rde.c | 150 ++++++++++++++++++++ |
| tests/libpldm_rde_test.cpp | 271 +++++++++++++++++++++++++++++++++++++ |
| 3 files changed, 512 insertions(+), 1 deletion(-) |
| |
| diff --git a/include/libpldm/pldm_rde.h b/include/libpldm/pldm_rde.h |
| index 3b8c1e8..5b2a3dc 100644 |
| --- a/include/libpldm/pldm_rde.h |
| +++ b/include/libpldm/pldm_rde.h |
| @@ -25,6 +25,7 @@ extern "C" { |
| #define PLDM_RDE_OPERATION_INIT_REQ_HDR_SIZE 17 |
| #define PLDM_RDE_OPERATION_INIT_RESP_HDR_SIZE 17 |
| #define PLDM_RDE_OPERATION_STATUS_RESP_HDR_SIZE 17 |
| +#define PLDM_RDE_OPERATION_ENUMERATE_RESP_HDR_SIZE 3 |
| |
| #define PLDM_RDE 0x06 /*Response should support PLDM_PLATFORM and PLDM_RDE*/ |
| #define RDE_NEGOTIATE_REDFISH_PARAMETERS_RESP_BYTES 12 |
| @@ -46,6 +47,7 @@ enum pldm_rde_commands { |
| PLDM_RDE_OPERATION_COMPLETE = 0x13, |
| PLDM_RDE_OPERATION_STATUS = 0x14, |
| PLDM_RDE_OPERATION_KILL = 0x15, |
| + PLDM_RDE_OPERATION_ENUMERATE = 0x16, |
| PLDM_RDE_MULTIPART_SEND = 0x30, |
| PLDM_RDE_MULTIPART_RECEIVE = 0x31, |
| }; |
| @@ -331,6 +333,26 @@ struct pldm_rde_operation_complete_req { |
| struct pldm_rde_operation_complete_resp { |
| uint8_t completion_code; |
| } __attribute__((packed)); |
| + |
| +/** |
| + * @brief RDEOperationEnumerate response operation data structure. |
| + */ |
| +struct pldm_rde_operation_enumerate_operation_data { |
| + uint32_t resource_id; |
| + uint16_t operation_id; |
| + uint8_t operation_type; |
| +} __attribute__((packed)); |
| + |
| +/** |
| + * @brief RDEOperationEnumerate response data structure. |
| + */ |
| +struct pldm_rde_operation_enumerate_resp { |
| + uint8_t completion_code; |
| + uint16_t operation_count; |
| + // Variable length data. |
| + uint8_t var_data[1]; |
| +} __attribute__((packed)); |
| + |
| /** |
| * @brief RDEOperationStatus request data structure. |
| */ |
| @@ -754,6 +776,74 @@ int encode_rde_operation_complete_resp(uint8_t instance_id, |
| int decode_rde_operation_complete_resp(const struct pldm_msg *msg, |
| size_t payload_length, |
| uint8_t *completion_code); |
| + |
| +/** |
| + * @brief Encode RDEOperationEnumerate request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[out] msg - Request will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_enumerate_req(uint8_t instance_id, |
| + struct pldm_msg *msg); |
| + |
| +/** |
| + * @brief Decode RDEOperationEnumerate request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_enumerate_req(const struct pldm_msg *msg, |
| + size_t payload_length); |
| + |
| +/** |
| + * @brief Encodes RDEOperationEnumerate response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_enumerate_resp(uint8_t instance_id, |
| + uint8_t completion_code, |
| + struct pldm_msg *msg); |
| + |
| +/** |
| + * @brief Updates encoded RDEOperationEnumerate response by appending operation |
| + * data to the response. |
| + * |
| + * @param[in] resource_id - Resource id |
| + * @param[in] operation_id - Operation Id |
| + * @param[in] operation_type - Operation type |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int update_encoded_rde_operation_enumerate_resp(const uint32_t resource_id, |
| + const uint16_t operation_id, |
| + const uint8_t operation_type, |
| + struct pldm_msg *msg); |
| + |
| +/** |
| + * @brief Decode RDEOperationEnumerate response. |
| + * NOTE: The operation_count and operation_data will have |
| + * valid data only when then completion_code is PLDM_SUCCESS |
| + * |
| + * @param[in] msg - Response message will be written to this. |
| + * @param[out] completion_code - PLDM completion code. |
| + * @param[out] operation_count - Number of active operations in RDE device. |
| + * @param[out] operation_data - An array of struct |
| + * pldm_rde_operation_enumerate_operation_data to store the operation data |
| + * @param[in] operation_data_array_size - Size of the input array of struct |
| + * pldm_rde_operation_enumerate_operation_data |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_enumerate_resp( |
| + const struct pldm_msg *msg, uint8_t *completion_code, |
| + uint16_t *operation_count, |
| + struct pldm_rde_operation_enumerate_operation_data *operation_data, |
| + uint16_t operation_data_array_size); |
| + |
| /** |
| * @brief Encode RDEOperationStatus request. |
| * |
| @@ -844,4 +934,4 @@ int decode_rde_operation_status_resp( |
| } |
| #endif |
| |
| -#endif /* PLDM_RDE_H */ |
| \ No newline at end of file |
| +#endif /* PLDM_RDE_H */ |
| diff --git a/src/pldm_rde.c b/src/pldm_rde.c |
| index 2c87f8e..7116827 100644 |
| --- a/src/pldm_rde.c |
| +++ b/src/pldm_rde.c |
| @@ -785,6 +785,156 @@ int decode_rde_operation_complete_resp(const struct pldm_msg *msg, |
| return PLDM_SUCCESS; |
| } |
| |
| +LIBPLDM_ABI_STABLE |
| +int encode_rde_operation_enumerate_req(uint8_t instance_id, |
| + struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_RDE_OPERATION_ENUMERATE; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +LIBPLDM_ABI_STABLE |
| +int decode_rde_operation_enumerate_req(const struct pldm_msg *msg, |
| + size_t payload_length) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + // Enumerate operation should not have any request payload |
| + if (payload_length != 0) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +LIBPLDM_ABI_STABLE |
| +int encode_rde_operation_enumerate_resp(uint8_t instance_id, |
| + uint8_t completion_code, |
| + struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + struct pldm_header_info header = {0}; |
| + header.msg_type = PLDM_RESPONSE; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.command = PLDM_RDE_OPERATION_ENUMERATE; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_enumerate_resp *response = |
| + (struct pldm_rde_operation_enumerate_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + |
| + // Initially set the operation count to 0. Operation data can be added |
| + // by calling update_encoded_rde_operation_enumerate_resp API |
| + response->operation_count = 0; |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +LIBPLDM_ABI_STABLE |
| +int update_encoded_rde_operation_enumerate_resp(const uint32_t resource_id, |
| + const uint16_t operation_id, |
| + const uint8_t operation_type, |
| + struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + struct pldm_rde_operation_enumerate_operation_data operation_data = {0}; |
| + operation_data.resource_id = htole32(resource_id); |
| + operation_data.operation_id = htole16(operation_id); |
| + operation_data.operation_type = operation_type; |
| + |
| + struct pldm_rde_operation_enumerate_resp *response = |
| + (struct pldm_rde_operation_enumerate_resp *)msg->payload; |
| + |
| + uint16_t operation_count = le16toh(response->operation_count); |
| + memcpy(response->var_data + |
| + (sizeof(struct pldm_rde_operation_enumerate_operation_data) * |
| + operation_count), |
| + (void *)&operation_data, |
| + sizeof(struct pldm_rde_operation_enumerate_operation_data)); |
| + |
| + response->operation_count = htole16(operation_count + 1); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +LIBPLDM_ABI_STABLE |
| +int decode_rde_operation_enumerate_resp( |
| + const struct pldm_msg *msg, uint8_t *completion_code, |
| + uint16_t *operation_count, |
| + struct pldm_rde_operation_enumerate_operation_data *operation_data, |
| + uint16_t operation_data_array_size) |
| +{ |
| + if (msg == NULL) { |
| + fprintf(stderr, "Invalid msg object\n"); |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + if ((completion_code == NULL) || (operation_count == NULL) || |
| + (operation_data == NULL)) { |
| + fprintf(stderr, "Invalid input pointers\n"); |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + struct pldm_rde_operation_enumerate_resp *response = |
| + (struct pldm_rde_operation_enumerate_resp *)msg->payload; |
| + |
| + *completion_code = response->completion_code; |
| + if (*completion_code != PLDM_SUCCESS) { |
| + fprintf( |
| + stderr, |
| + "Unsuccessful completion code received in op status: %x\n", |
| + (uint8_t)(*completion_code)); |
| + return PLDM_SUCCESS; |
| + } |
| + |
| + *operation_count = le16toh(response->operation_count); |
| + if (operation_data_array_size < *operation_count) { |
| + fprintf(stderr, |
| + "Input operation_data struct array too small\n"); |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + for (uint16_t i = 0; i < *operation_count; i++) { |
| + struct pldm_rde_operation_enumerate_operation_data |
| + native_operation_data; |
| + memcpy( |
| + (void *)&native_operation_data, |
| + response->var_data + |
| + i * sizeof(struct |
| + pldm_rde_operation_enumerate_operation_data), |
| + sizeof(struct pldm_rde_operation_enumerate_operation_data)); |
| + operation_data[i].resource_id = |
| + le32toh(native_operation_data.resource_id); |
| + operation_data[i].operation_id = |
| + le16toh(native_operation_data.operation_id); |
| + operation_data[i].operation_type = |
| + native_operation_data.operation_type; |
| + } |
| + |
| + return PLDM_SUCCESS; |
| +} |
| + |
| LIBPLDM_ABI_STABLE |
| int encode_rde_operation_status_req(uint8_t instance_id, uint32_t resource_id, |
| uint16_t operation_id, struct pldm_msg *msg) |
| diff --git a/tests/libpldm_rde_test.cpp b/tests/libpldm_rde_test.cpp |
| index 56e322b..ed4625e 100644 |
| --- a/tests/libpldm_rde_test.cpp |
| +++ b/tests/libpldm_rde_test.cpp |
| @@ -887,3 +887,274 @@ TEST(RDEOperationStatus, DecodeResponseSuccess) |
| EXPECT_EQ(returnEtag->string_length_bytes, |
| std::end(etag) - std::begin(etag)); |
| } |
| + |
| +TEST(RDEOperationEnumerate, EncodeRequest) |
| +{ |
| + uint8_t instanceId = 23; |
| + |
| + constexpr size_t requestSize = sizeof(struct pldm_msg_hdr); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + // When input msg of type struct pldm_msg * is NULL |
| + EXPECT_EQ(encode_rde_operation_enumerate_req(instanceId, NULL), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When all inputs are valid |
| + EXPECT_EQ(encode_rde_operation_enumerate_req(instanceId, request), |
| + PLDM_SUCCESS); |
| + |
| + // Test Header values |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.request, PLDM_REQUEST); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.command, PLDM_RDE_OPERATION_ENUMERATE); |
| +} |
| + |
| +TEST(RDEOperationEnumerate, DecodeRequest) |
| +{ |
| + uint8_t instanceId = 25; |
| + |
| + constexpr size_t requestSize = sizeof(struct pldm_msg_hdr); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + encode_rde_operation_enumerate_req(instanceId, request); |
| + |
| + // When input msg of type struct pldm_msg * is NULL |
| + EXPECT_EQ(decode_rde_operation_enumerate_req( |
| + NULL, requestSize - sizeof(struct pldm_msg_hdr)), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When when the request size in non-zero indicating a request payload is |
| + // present |
| + EXPECT_EQ(decode_rde_operation_enumerate_req(request, 10), |
| + PLDM_ERROR_INVALID_LENGTH); |
| + |
| + // When all inputs are valid |
| + EXPECT_EQ(decode_rde_operation_enumerate_req( |
| + request, requestSize - sizeof(struct pldm_msg_hdr)), |
| + PLDM_SUCCESS); |
| +} |
| + |
| +TEST(RDEOperationEnumerate, EncodeResponse) |
| +{ |
| + uint8_t instanceId = 29; |
| + uint8_t completionCode = 0; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + PLDM_RDE_OPERATION_ENUMERATE_RESP_HDR_SIZE; |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + // When input msg of type struct pldm_msg* is NULL |
| + EXPECT_EQ( |
| + encode_rde_operation_enumerate_resp(instanceId, completionCode, NULL), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When all the inputs are valid |
| + EXPECT_EQ(encode_rde_operation_enumerate_resp(instanceId, completionCode, |
| + response), |
| + PLDM_SUCCESS); |
| + |
| + // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_RDE_OPERATION_ENUMERATE); |
| + |
| + // verify payload. |
| + auto respPayload = |
| + reinterpret_cast<pldm_rde_operation_enumerate_resp*>(response->payload); |
| + EXPECT_EQ(respPayload->completion_code, completionCode); |
| + EXPECT_EQ(respPayload->operation_count, 0); |
| +} |
| + |
| +TEST(RDEOperationEnumerate, UpdateEncodedResponse) |
| +{ |
| + uint8_t instanceId = 29; |
| + uint8_t completionCode = 0; |
| + const uint16_t operationCount = 3; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + PLDM_RDE_OPERATION_ENUMERATE_RESP_HDR_SIZE + |
| + (operationCount * |
| + sizeof(struct pldm_rde_operation_enumerate_operation_data)); |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_operation_enumerate_resp(instanceId, completionCode, |
| + response), |
| + PLDM_SUCCESS); |
| + |
| + struct pldm_rde_operation_enumerate_operation_data |
| + enumerateData[operationCount] = { |
| + {.resource_id = 54314, |
| + .operation_id = 2, |
| + .operation_type = PLDM_RDE_OPERATION_READ}, |
| + {.resource_id = 32456, |
| + .operation_id = 1, |
| + .operation_type = PLDM_RDE_OPERATION_UPDATE}, |
| + {.resource_id = 76543, |
| + .operation_id = 6, |
| + .operation_type = PLDM_RDE_OPERATION_ACTION}}; |
| + |
| + // When input msg of type struct pldm_msg* is NULL |
| + EXPECT_EQ(update_encoded_rde_operation_enumerate_resp( |
| + enumerateData[0].resource_id, enumerateData[0].operation_id, |
| + enumerateData[0].operation_type, NULL), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // Update the encoded payload with enumerate_data one by one and verify that |
| + // response payload metadata gets updated accordingly |
| + for (int i = 0; i < operationCount; i++) |
| + { |
| + |
| + EXPECT_EQ(update_encoded_rde_operation_enumerate_resp( |
| + enumerateData[i].resource_id, |
| + enumerateData[i].operation_id, |
| + enumerateData[i].operation_type, response), |
| + PLDM_SUCCESS); |
| + auto respPayload2 = |
| + reinterpret_cast<pldm_rde_operation_enumerate_resp*>( |
| + response->payload); |
| + EXPECT_EQ(respPayload2->completion_code, completionCode); |
| + EXPECT_EQ(respPayload2->operation_count, i + 1); |
| + } |
| + |
| + // verify payload. |
| + auto respPayload3 = |
| + reinterpret_cast<pldm_rde_operation_enumerate_resp*>(response->payload); |
| + EXPECT_EQ(respPayload3->completion_code, completionCode); |
| + EXPECT_EQ(respPayload3->operation_count, operationCount); |
| + |
| + struct pldm_rde_operation_enumerate_operation_data* enumerateRespData = |
| + (struct pldm_rde_operation_enumerate_operation_data*) |
| + respPayload3->var_data; |
| + |
| + // Verify that the enumerate_data in the response is updated |
| + for (int i = 0; i < operationCount; i++) |
| + { |
| + EXPECT_EQ(enumerateRespData[i].resource_id, |
| + enumerateData[i].resource_id); |
| + EXPECT_EQ(enumerateRespData[i].operation_id, |
| + enumerateData[i].operation_id); |
| + EXPECT_EQ(enumerateRespData[i].operation_type, |
| + enumerateData[i].operation_type); |
| + } |
| +} |
| + |
| +TEST(RDEOperationEnumerate, DecodeResponse) |
| +{ |
| + uint8_t instanceId = 29; |
| + uint8_t completionCodeInput = 0; |
| + const uint16_t operationCountInput = 3; |
| + |
| + uint8_t completionCodeOutput = 0; |
| + uint16_t operationCountOutput = 0; |
| + |
| + struct pldm_rde_operation_enumerate_operation_data |
| + enumerateRespData[operationCountInput]; |
| + |
| + struct pldm_rde_operation_enumerate_operation_data |
| + enumerateData[operationCountInput] = { |
| + {.resource_id = 54314, |
| + .operation_id = 2, |
| + .operation_type = PLDM_RDE_OPERATION_READ}, |
| + {.resource_id = 32456, |
| + .operation_id = 1, |
| + .operation_type = PLDM_RDE_OPERATION_UPDATE}, |
| + {.resource_id = 76543, |
| + .operation_id = 6, |
| + .operation_type = PLDM_RDE_OPERATION_ACTION}}; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + PLDM_RDE_OPERATION_ENUMERATE_RESP_HDR_SIZE + |
| + (operationCountInput * |
| + sizeof(struct pldm_rde_operation_enumerate_operation_data)); |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + // When input msg of type struct pldm_msg* is NULL |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + NULL, &completionCodeOutput, &operationCountOutput, |
| + enumerateRespData, operationCountInput), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When input completion_code is NULL |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + response, NULL, &operationCountOutput, enumerateRespData, |
| + operationCountInput), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When input operation_count is NULL |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + response, &completionCodeOutput, NULL, enumerateRespData, |
| + operationCountInput), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When input operation_data is NULL |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + response, &completionCodeOutput, &operationCountOutput, NULL, |
| + operationCountInput), |
| + PLDM_ERROR_INVALID_DATA); |
| + |
| + // When input array size is smaller that the actual operation count |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + response, &completionCodeOutput, &operationCountOutput, |
| + enumerateRespData, operationCountInput - 1), |
| + PLDM_SUCCESS); |
| + |
| + // When all the inputs are valid |
| + EXPECT_EQ(encode_rde_operation_enumerate_resp( |
| + instanceId, completionCodeInput, response), |
| + PLDM_SUCCESS); |
| + |
| + // Update the encoded payload with enumerate_data one by one |
| + for (int i = 0; i < operationCountInput; i++) |
| + { |
| + EXPECT_EQ(update_encoded_rde_operation_enumerate_resp( |
| + enumerateData[i].resource_id, |
| + enumerateData[i].operation_id, |
| + enumerateData[i].operation_type, response), |
| + PLDM_SUCCESS); |
| + } |
| + |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + response, &completionCodeOutput, &operationCountOutput, |
| + enumerateRespData, operationCountInput), |
| + PLDM_SUCCESS); |
| + |
| + auto respPayload1 = |
| + reinterpret_cast<pldm_rde_operation_enumerate_resp*>(response->payload); |
| + EXPECT_EQ(respPayload1->completion_code, completionCodeInput); |
| + EXPECT_EQ(respPayload1->operation_count, operationCountInput); |
| + |
| + // Verify that the enumerate_data in the response is updated |
| + for (int i = 0; i < operationCountInput; i++) |
| + { |
| + EXPECT_EQ(enumerateRespData[i].resource_id, |
| + enumerateData[i].resource_id); |
| + EXPECT_EQ(enumerateRespData[i].operation_id, |
| + enumerateData[i].operation_id); |
| + EXPECT_EQ(enumerateRespData[i].operation_type, |
| + enumerateData[i].operation_type); |
| + } |
| + |
| + // When encoder encounters error and sets error completion code |
| + EXPECT_EQ( |
| + encode_rde_operation_enumerate_resp(instanceId, PLDM_ERROR, response), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(decode_rde_operation_enumerate_resp( |
| + response, &completionCodeOutput, &operationCountOutput, |
| + enumerateRespData, operationCountInput), |
| + PLDM_SUCCESS); |
| + |
| + auto respPayload2 = |
| + reinterpret_cast<pldm_rde_operation_enumerate_resp*>(response->payload); |
| + EXPECT_EQ(respPayload2->completion_code, PLDM_ERROR); |
| + EXPECT_EQ(respPayload2->operation_count, 0); |
| +} |
| -- |
| 2.43.0.594.gd9cf4e227d-goog |
| |