libpldm: Implement encode/decode for GetNumericEffecterValue
The spec of GetNumericEffecterValue command refers to DSP0248_1.2.0:22.3

Change-Id: Ief5e00859d23c981611736b6ee257b182f0e6809
Signed-off-by: Jolie Ku <jolie_ku@wistron.com>
diff --git a/libpldm/platform.c b/libpldm/platform.c
index 48df1ad..5dd388e 100644
--- a/libpldm/platform.c
+++ b/libpldm/platform.c
@@ -756,3 +756,186 @@
 	}
 	return PLDM_SUCCESS;
 }
+
+int encode_get_numeric_effecter_value_req(uint8_t instance_id,
+					  uint16_t effecter_id,
+					  struct pldm_msg *msg)
+{
+	struct pldm_header_info header = {0};
+	int rc = PLDM_SUCCESS;
+
+	if (msg == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	struct pldm_get_numeric_effecter_value_req *request =
+	    (struct pldm_get_numeric_effecter_value_req *)msg->payload;
+
+	header.msg_type = PLDM_REQUEST;
+	header.instance = instance_id;
+	header.pldm_type = PLDM_PLATFORM;
+	header.command = PLDM_GET_NUMERIC_EFFECTER_VALUE;
+
+	if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+		return rc;
+	}
+
+	request->effecter_id = htole16(effecter_id);
+
+	return PLDM_SUCCESS;
+}
+
+int encode_get_numeric_effecter_value_resp(
+    uint8_t instance_id, uint8_t completion_code, uint8_t effecter_data_size,
+    uint8_t effecter_oper_state, uint8_t *pending_value, uint8_t *present_value,
+    struct pldm_msg *msg, size_t payload_length)
+{
+	struct pldm_header_info header = {0};
+	int rc = PLDM_SUCCESS;
+
+	if (msg == NULL || pending_value == NULL || present_value == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (effecter_oper_state > EFFECTER_OPER_STATE_INTEST) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	header.msg_type = PLDM_RESPONSE;
+	header.instance = instance_id;
+	header.pldm_type = PLDM_PLATFORM;
+	header.command = PLDM_GET_NUMERIC_EFFECTER_VALUE;
+
+	if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+		return rc;
+	}
+
+	struct pldm_get_numeric_effecter_value_resp *response =
+	    (struct pldm_get_numeric_effecter_value_resp *)msg->payload;
+
+	response->completion_code = completion_code;
+	response->effecter_data_size = effecter_data_size;
+	response->effecter_oper_state = effecter_oper_state;
+
+	if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
+	    effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
+		if (payload_length !=
+		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES) {
+			return PLDM_ERROR_INVALID_LENGTH;
+		}
+		response->pending_and_present_values[0] = *pending_value;
+		response->pending_and_present_values[1] = *present_value;
+
+	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
+		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
+		if (payload_length !=
+		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 2) {
+			return PLDM_ERROR_INVALID_LENGTH;
+		}
+		memcpy(response->pending_and_present_values, pending_value, 2);
+		memcpy(&response->pending_and_present_values[2], present_value,
+		       2);
+
+	} else if (effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
+		   effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
+		if (payload_length !=
+		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 6) {
+			return PLDM_ERROR_INVALID_LENGTH;
+		}
+		memcpy(response->pending_and_present_values, pending_value, 4);
+		memcpy(&response->pending_and_present_values[4], present_value,
+		       4);
+	}
+	return PLDM_SUCCESS;
+}
+
+int decode_get_numeric_effecter_value_req(const struct pldm_msg *msg,
+					  size_t payload_length,
+					  uint16_t *effecter_id)
+{
+	if (msg == NULL || effecter_id == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (payload_length != PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES) {
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	struct pldm_get_numeric_effecter_value_req *request =
+	    (struct pldm_get_numeric_effecter_value_req *)msg->payload;
+
+	*effecter_id = le16toh(request->effecter_id);
+
+	return PLDM_SUCCESS;
+}
+
+int decode_get_numeric_effecter_value_resp(
+    const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code,
+    uint8_t *effecter_data_size, uint8_t *effecter_oper_state,
+    uint8_t *pending_value, uint8_t *present_value)
+{
+	if (msg == NULL || effecter_data_size == NULL ||
+	    effecter_oper_state == NULL || pending_value == NULL ||
+	    present_value == NULL) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	*completion_code = msg->payload[0];
+	if (PLDM_SUCCESS != *completion_code) {
+		return PLDM_SUCCESS;
+	}
+
+	if (payload_length < PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES) {
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	struct pldm_get_numeric_effecter_value_resp *response =
+	    (struct pldm_get_numeric_effecter_value_resp *)msg->payload;
+
+	*effecter_data_size = response->effecter_data_size;
+	*effecter_oper_state = response->effecter_oper_state;
+
+	if (*effecter_data_size > PLDM_EFFECTER_DATA_SIZE_SINT32) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (*effecter_oper_state > EFFECTER_OPER_STATE_INTEST) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	if (*effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT8 ||
+	    *effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT8) {
+		if (payload_length !=
+		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES) {
+			return PLDM_ERROR_INVALID_LENGTH;
+		}
+		memcpy(pending_value, response->pending_and_present_values, 1);
+		memcpy(present_value, &response->pending_and_present_values[1],
+		       1);
+
+	} else if (*effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT16 ||
+		   *effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT16) {
+		if (payload_length !=
+		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 2) {
+			return PLDM_ERROR_INVALID_LENGTH;
+		}
+		memcpy(pending_value, response->pending_and_present_values, 2);
+		memcpy(present_value, &response->pending_and_present_values[2],
+		       2);
+
+	} else if (*effecter_data_size == PLDM_EFFECTER_DATA_SIZE_UINT32 ||
+		   *effecter_data_size == PLDM_EFFECTER_DATA_SIZE_SINT32) {
+		if (payload_length !=
+		    PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 6) {
+			return PLDM_ERROR_INVALID_LENGTH;
+		}
+		memcpy(pending_value, response->pending_and_present_values, 4);
+		memcpy(present_value, &response->pending_and_present_values[4],
+		       4);
+	}
+	return PLDM_SUCCESS;
+}
\ No newline at end of file
diff --git a/libpldm/platform.h b/libpldm/platform.h
index 82c2b28..0ee050a 100644
--- a/libpldm/platform.h
+++ b/libpldm/platform.h
@@ -14,6 +14,7 @@
 /* Maximum size for request */
 #define PLDM_SET_STATE_EFFECTER_STATES_REQ_BYTES 19
 #define PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES 4
+#define PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES 2
 /* Response lengths are inclusive of completion code */
 #define PLDM_SET_STATE_EFFECTER_STATES_RESP_BYTES 1
 #define PLDM_GET_STATE_SENSOR_READINGS_RESP_BYTES 34
@@ -24,6 +25,7 @@
 #define PLDM_GET_PDR_REQ_BYTES 13
 /* Minimum response length */
 #define PLDM_GET_PDR_MIN_RESP_BYTES 12
+#define PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES 5
 
 /* Minimum length for PLDM PlatformEventMessage request */
 #define PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES 3
@@ -77,9 +79,22 @@
 	UPPERFATAL = 0x0a
 };
 
+enum pldm_effecter_oper_state {
+	EFFECTER_OPER_STATE_ENABLED_UPDATEPENDING,
+	EFFECTER_OPER_STATE_ENABLED_NOUPDATEPENDING,
+	EFFECTER_OPER_STATE_DISABLED,
+	EFFECTER_OPER_STATE_UNAVAILABLE,
+	EFFECTER_OPER_STATE_STATUSUNKNOWN,
+	EFFECTER_OPER_STATE_FAILED,
+	EFFECTER_OPER_STATE_INITIALIZING,
+	EFFECTER_OPER_STATE_SHUTTINGDOWN,
+	EFFECTER_OPER_STATE_INTEST
+};
+
 enum pldm_platform_commands {
 	PLDM_GET_STATE_SENSOR_READINGS = 0x21,
 	PLDM_SET_NUMERIC_EFFECTER_VALUE = 0x31,
+	PLDM_GET_NUMERIC_EFFECTER_VALUE = 0x32,
 	PLDM_SET_STATE_EFFECTER_STATES = 0x39,
 	PLDM_GET_PDR = 0x51,
 	PLDM_PLATFORM_EVENT_MESSAGE = 0x0A
@@ -398,6 +413,25 @@
 	uint32_t change_entry[1];
 } __attribute__((packed));
 
+/** @struct pldm_get_numeric_effecter_value_req
+ *
+ *  structure representing GetNumericEffecterValue request packet
+ */
+struct pldm_get_numeric_effecter_value_req {
+	uint16_t effecter_id;
+} __attribute__((packed));
+
+/** @struct pldm_get_numeric_effecter_value_resp
+ *
+ *  structure representing GetNumericEffecterValue response packet
+ */
+struct pldm_get_numeric_effecter_value_resp {
+	uint8_t completion_code;
+	uint8_t effecter_data_size;
+	uint8_t effecter_oper_state;
+	uint8_t pending_and_present_values[1];
+} __attribute__((packed));
+
 /* Responder */
 
 /* SetNumericEffecterValue */
@@ -565,6 +599,44 @@
 					  get_sensor_state_field *field,
 					  struct pldm_msg *msg);
 
+/* GetNumericEffecterValue */
+
+/** @brief Decode GetNumericEffecterValue request data
+ *
+ *  @param[in] msg - Request message
+ *  @param[in] payload_length - Length of request message payload
+ *  @param[out] effecter_id - used to identify and access the effecter
+ *  @return pldm_completion_codes
+ */
+int decode_get_numeric_effecter_value_req(const struct pldm_msg *msg,
+					  size_t payload_length,
+					  uint16_t *effecter_id);
+
+/** @brief Create a PLDM response message for GetNumericEffecterValue
+ *
+ *  @param[in] instance_id - Message's instance id
+ *  @param[in] completion_code - PLDM completion code
+ *  @param[in] effecter_data_size - The bit width and format of the setting
+ *             value for the effecter.
+ * 	       value:{uint8,sint8,uint16,sint16,uint32,sint32}
+ *  @param[in] effecter_oper_state - The state of the effecter itself
+ *  @param[in] pending_value - The pending numeric value setting of the
+ *             effecter. The effecterDataSize field indicates the number of
+ *             bits used for this field
+ *  @param[in] present_value - The present numeric value setting of the
+ *             effecter. The effecterDataSize indicates the number of bits
+ *             used for this field
+ *  @param[out] msg - Message will be written to this
+ *  @param[in] payload_length - Length of request message payload
+ *  @return pldm_completion_codes
+ *  @note  Caller is responsible for memory alloc and dealloc of param
+ *         'msg.payload'
+ */
+int encode_get_numeric_effecter_value_resp(
+    uint8_t instance_id, uint8_t completion_code, uint8_t effecter_data_size,
+    uint8_t effecter_oper_state, uint8_t *pending_value, uint8_t *present_value,
+    struct pldm_msg *msg, size_t payload_length);
+
 /* Requester */
 
 /* GetPDR */
@@ -846,6 +918,43 @@
 			       uint8_t *sensor_data_size,
 			       uint32_t *present_reading);
 
+/* GetNumericEffecterValue */
+
+/** @brief Create a PLDM request message for GetNumericEffecterValue
+ *
+ *  @param[in] instance_id - Message's instance id
+ *  @param[in] effecter_id - used to identify and access the effecter
+ *  @param[out] msg - Message will be written to this
+ *  @return pldm_completion_codes
+ *  @note  Caller is responsible for memory alloc and dealloc of param
+ *         'msg.payload'
+ */
+int encode_get_numeric_effecter_value_req(uint8_t instance_id,
+					  uint16_t effecter_id,
+					  struct pldm_msg *msg);
+
+/** @brief Create a PLDM response message for GetNumericEffecterValue
+ *
+ *  @param[in] msg - Request message
+ *  @param[in] payload_length - Length of request message payload
+ *  @param[out] completion_code - PLDM completion code
+ *  @param[out] effecter_data_size - The bit width and format of the setting
+ *		value for the effecter.
+ *		value:{uint8,sint8,uint16,sint16,uint32,sint32}
+ *  @param[out] effecter_oper_state - The state of the effecter itself
+ *  @param[out] pending_value - The pending numeric value setting of the
+ *              effecter. The effecterDataSize field indicates the number of
+ *              bits used for this field
+ *  @param[out] present_value - The present numeric value setting of the
+ *              effecter. The effecterDataSize indicates the number of bits
+ *              used for this field
+ *  @return pldm_completion_codes
+ */
+int decode_get_numeric_effecter_value_resp(
+    const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code,
+    uint8_t *effecter_data_size, uint8_t *effecter_oper_state,
+    uint8_t *pending_value, uint8_t *present_value);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libpldm/tests/libpldm_platform_test.cpp b/libpldm/tests/libpldm_platform_test.cpp
index 1261d0b..548ab05 100644
--- a/libpldm/tests/libpldm_platform_test.cpp
+++ b/libpldm/tests/libpldm_platform_test.cpp
@@ -1119,3 +1119,245 @@
         &eventState, &previousEventState, &sensorDataSize, &presentReading);
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
 }
+
+TEST(GetNumericEffecterValue, testGoodEncodeRequest)
+{
+    std::vector<uint8_t> requestMsg(hdrSize +
+                                    PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES);
+
+    uint16_t effecter_id = 0xAB01;
+
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+    auto rc = encode_get_numeric_effecter_value_req(0, effecter_id, request);
+
+    struct pldm_get_numeric_effecter_value_req* req =
+        reinterpret_cast<struct pldm_get_numeric_effecter_value_req*>(
+            request->payload);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(effecter_id, le16toh(req->effecter_id));
+}
+
+TEST(GetNumericEffecterValue, testBadEncodeRequest)
+{
+    std::vector<uint8_t> requestMsg(
+        hdrSize + PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES);
+
+    auto rc = encode_get_numeric_effecter_value_req(0, 0, nullptr);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetNumericEffecterValue, testGoodDecodeRequest)
+{
+    std::array<uint8_t, hdrSize + PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES>
+        requestMsg{};
+
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    struct pldm_get_numeric_effecter_value_req* req =
+        reinterpret_cast<struct pldm_get_numeric_effecter_value_req*>(
+            request->payload);
+
+    uint16_t effecter_id = 0x12AB;
+    req->effecter_id = htole16(effecter_id);
+
+    uint16_t reteffecter_id;
+
+    auto rc = decode_get_numeric_effecter_value_req(
+        request, requestMsg.size() - hdrSize, &reteffecter_id);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(effecter_id, reteffecter_id);
+}
+
+TEST(GetNumericEffecterValue, testBadDecodeRequest)
+{
+    std::array<uint8_t, hdrSize + PLDM_GET_NUMERIC_EFFECTER_VALUE_REQ_BYTES>
+        requestMsg{};
+
+    auto rc = decode_get_numeric_effecter_value_req(
+        nullptr, requestMsg.size() - hdrSize, nullptr);
+
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    struct pldm_set_numeric_effecter_value_req* req =
+        reinterpret_cast<struct pldm_set_numeric_effecter_value_req*>(
+            request->payload);
+
+    uint16_t effecter_id = 0x1A;
+    req->effecter_id = htole16(effecter_id);
+    uint16_t reteffecter_id;
+
+    rc = decode_get_numeric_effecter_value_req(
+        request, requestMsg.size() - hdrSize - 1, &reteffecter_id);
+
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetNumericEffecterValue, testGoodEncodeResponse)
+{
+    uint8_t completionCode = 0;
+    uint8_t effecter_dataSize = PLDM_EFFECTER_DATA_SIZE_UINT32;
+    uint8_t effecter_operState = EFFECTER_OPER_STATE_ENABLED_NOUPDATEPENDING;
+    uint32_t pendingValue = 0x12345678;
+    uint32_t presentValue = 0xABCDEF00;
+
+    std::array<uint8_t,
+               hdrSize + PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 6>
+        responseMsg{};
+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    uint32_t pendingValue_le = htole32(pendingValue);
+    uint32_t presentValue_le = htole32(presentValue);
+
+    auto rc = encode_get_numeric_effecter_value_resp(
+        0, completionCode, effecter_dataSize, effecter_operState,
+        reinterpret_cast<uint8_t*>(&pendingValue_le),
+        reinterpret_cast<uint8_t*>(&presentValue_le), response,
+        responseMsg.size() - hdrSize);
+
+    struct pldm_get_numeric_effecter_value_resp* resp =
+        reinterpret_cast<struct pldm_get_numeric_effecter_value_resp*>(
+            response->payload);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(effecter_dataSize, resp->effecter_data_size);
+    EXPECT_EQ(effecter_operState, resp->effecter_oper_state);
+    EXPECT_EQ(pendingValue, le32toh(*(reinterpret_cast<uint32_t*>(
+                                &resp->pending_and_present_values[0]))));
+    EXPECT_EQ(presentValue, le32toh(*(reinterpret_cast<uint32_t*>(
+                                &resp->pending_and_present_values[4]))));
+}
+
+TEST(GetNumericEffecterValue, testBadEncodeResponse)
+{
+    std::array<uint8_t,
+               hdrSize + PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 2>
+        responseMsg{};
+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    uint8_t pendingValue = 0x01;
+    uint8_t presentValue = 0x02;
+
+    auto rc = encode_get_numeric_effecter_value_resp(
+        0, PLDM_SUCCESS, 0, 0, nullptr, nullptr, nullptr,
+        responseMsg.size() - hdrSize);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = encode_get_numeric_effecter_value_resp(
+        0, PLDM_SUCCESS, 6, 9, reinterpret_cast<uint8_t*>(&pendingValue),
+        reinterpret_cast<uint8_t*>(&presentValue), response,
+        responseMsg.size() - hdrSize);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    uint8_t effecter_dataSize = PLDM_EFFECTER_DATA_SIZE_UINT8;
+    uint8_t effecter_operState = EFFECTER_OPER_STATE_FAILED;
+
+    rc = encode_get_numeric_effecter_value_resp(
+        0, PLDM_SUCCESS, effecter_dataSize, effecter_operState,
+        reinterpret_cast<uint8_t*>(&pendingValue),
+        reinterpret_cast<uint8_t*>(&presentValue), response,
+        responseMsg.size() - hdrSize);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetNumericEffecterValue, testGoodDecodeResponse)
+{
+    std::array<uint8_t,
+               hdrSize + PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 2>
+        responseMsg{};
+
+    uint8_t completionCode = 0;
+    uint8_t effecter_dataSize = PLDM_EFFECTER_DATA_SIZE_UINT16;
+    uint8_t effecter_operState = EFFECTER_OPER_STATE_ENABLED_NOUPDATEPENDING;
+    uint16_t pendingValue = 0x4321;
+    uint16_t presentValue = 0xDCBA;
+
+    uint8_t retcompletionCode;
+    uint8_t reteffecter_dataSize;
+    uint8_t reteffecter_operState;
+    uint8_t retpendingValue[2];
+    uint8_t retpresentValue[2];
+
+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    struct pldm_get_numeric_effecter_value_resp* resp =
+        reinterpret_cast<struct pldm_get_numeric_effecter_value_resp*>(
+            response->payload);
+
+    resp->completion_code = completionCode;
+    resp->effecter_data_size = effecter_dataSize;
+    resp->effecter_oper_state = effecter_operState;
+
+    uint16_t pendingValue_le = htole16(pendingValue);
+    memcpy(resp->pending_and_present_values, &pendingValue_le,
+           sizeof(pendingValue_le));
+    uint16_t presentValue_le = htole16(presentValue);
+    memcpy(&resp->pending_and_present_values[2], &presentValue_le,
+           sizeof(presentValue_le));
+
+    auto rc = decode_get_numeric_effecter_value_resp(
+        response, responseMsg.size() - hdrSize, &retcompletionCode,
+        &reteffecter_dataSize, &reteffecter_operState, retpendingValue,
+        retpresentValue);
+
+    uint16_t retpending_value =
+        le16toh(*(reinterpret_cast<uint16_t*>(retpendingValue)));
+    uint16_t retpresent_value =
+        le16toh(*(reinterpret_cast<uint16_t*>(retpresentValue)));
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(completionCode, retcompletionCode);
+    EXPECT_EQ(effecter_dataSize, reteffecter_dataSize);
+    EXPECT_EQ(effecter_operState, reteffecter_operState);
+    EXPECT_EQ(pendingValue, retpending_value);
+    EXPECT_EQ(presentValue, retpresent_value);
+}
+
+TEST(GetNumericEffecterValue, testBadDecodeResponse)
+{
+    std::array<uint8_t,
+               hdrSize + PLDM_GET_NUMERIC_EFFECTER_VALUE_MIN_RESP_BYTES + 6>
+        responseMsg{};
+
+    auto rc = decode_get_numeric_effecter_value_resp(
+        nullptr, responseMsg.size() - hdrSize, nullptr, nullptr, nullptr,
+        nullptr, nullptr);
+
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    uint8_t completionCode = 0;
+    uint8_t effecter_dataSize = PLDM_EFFECTER_DATA_SIZE_SINT16;
+    uint8_t effecter_operState = EFFECTER_OPER_STATE_DISABLED;
+    uint16_t pendingValue = 0x5678;
+    uint16_t presentValue = 0xCDEF;
+
+    uint8_t retcompletionCode;
+    uint8_t reteffecter_dataSize;
+    uint8_t reteffecter_operState;
+    uint8_t retpendingValue[2];
+    uint8_t retpresentValue[2];
+
+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    struct pldm_get_numeric_effecter_value_resp* resp =
+        reinterpret_cast<struct pldm_get_numeric_effecter_value_resp*>(
+            response->payload);
+
+    resp->completion_code = completionCode;
+    resp->effecter_data_size = effecter_dataSize;
+    resp->effecter_oper_state = effecter_operState;
+
+    uint16_t pendingValue_le = htole16(pendingValue);
+    memcpy(resp->pending_and_present_values, &pendingValue_le,
+           sizeof(pendingValue_le));
+    uint16_t presentValue_le = htole16(presentValue);
+    memcpy(&resp->pending_and_present_values[2], &presentValue_le,
+           sizeof(presentValue_le));
+
+    rc = decode_get_numeric_effecter_value_resp(
+        response, responseMsg.size() - hdrSize, &retcompletionCode,
+        &reteffecter_dataSize, &reteffecter_operState, retpendingValue,
+        retpresentValue);
+
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}