Add numeric sensor PDR and sensor aux names PDR

1. Added struct for numeric sensor PDR in DSP0248_1.2.2 table78 and
decode_numeric_sensor_pdr_data API to unpack pdr data to struct
2. Added struct for sensor auxiliary names PDR in DSP0248_1.2.2 table83

Signed-off-by: Gilbert Chen <gilbertc@nvidia.com>
Change-Id: I11d25ee7da8326a5f5fe2c8a237ac014882e436e
diff --git a/include/libpldm/platform.h b/include/libpldm/platform.h
index af92885..9380bc9 100644
--- a/include/libpldm/platform.h
+++ b/include/libpldm/platform.h
@@ -62,9 +62,22 @@
 #define PLDM_PDR_REPOSITORY_CHG_EVENT_MIN_LENGTH 2
 #define PLDM_PDR_REPOSITORY_CHANGE_RECORD_MIN_LENGTH 2
 
+/* Minimum length of numeric sensor PDR */
+#define PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH 57
+#define PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH 3
+#define PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH 9
+#define PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH                                 \
+	(PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +                            \
+	 PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +      \
+	 PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH)
+
 #define PLDM_INVALID_EFFECTER_ID 0xFFFF
 #define PLDM_TID_RESERVED 0xFF
 
+/* DSP0248 Table1 PLDM monitoring and control data types */
+#define PLDM_STR_UTF_8_MAX_LEN 256
+#define PLDM_STR_UTF_16_MAX_LEN 256
+
 enum pldm_effecter_data_size {
 	PLDM_EFFECTER_DATA_SIZE_UINT8,
 	PLDM_EFFECTER_DATA_SIZE_SINT8,
@@ -83,6 +96,7 @@
 	PLDM_RANGE_FIELD_FORMAT_SINT32,
 	PLDM_RANGE_FIELD_FORMAT_REAL32
 };
+#define PLDM_RANGE_FIELD_FORMAT_MAX PLDM_RANGE_FIELD_FORMAT_REAL32
 
 enum set_request { PLDM_NO_CHANGE = 0x00, PLDM_REQUEST_SET = 0x01 };
 
@@ -256,6 +270,7 @@
 	PLDM_SENSOR_DATA_SIZE_UINT32,
 	PLDM_SENSOR_DATA_SIZE_SINT32
 };
+#define PLDM_SENSOR_DATA_SIZE_MAX PLDM_SENSOR_DATA_SIZE_SINT32
 
 /** @brief PLDM PlatformEventMessage response status
  */
@@ -448,6 +463,18 @@
 	uint8_t terminus_locator_value[1];
 } __attribute__((packed));
 
+/** @struct pldm_sensor_auxiliary_names_pdr
+ *
+ *  Structure representing PLDM Sensor Auxiliary Names PDR
+ */
+struct pldm_sensor_auxiliary_names_pdr {
+	struct pldm_pdr_hdr hdr;
+	uint16_t terminus_handle;
+	uint16_t sensor_id;
+	uint8_t sensor_count;
+	uint8_t names[1];
+} __attribute__((packed));
+
 /** @struct pldm_terminus_locator_type_mctp_eid
  *
  *  Structure representing terminus locator value for
@@ -647,6 +674,84 @@
 	union_range_field_format rated_min;
 } __attribute__((packed));
 
+/** @union union_sensor_data_size
+ *
+ *  The bit width and format of reading and threshold values that the sensor
+ *  returns.
+ *  Refer to: DSP0248_1.2.0: 28.4 Table 78
+ */
+typedef union {
+	uint8_t value_u8;
+	int8_t value_s8;
+	uint16_t value_u16;
+	int16_t value_s16;
+	uint32_t value_u32;
+	int32_t value_s32;
+} union_sensor_data_size;
+
+/** @struct pldm_value_pdr_hdr
+ *
+ *  Structure representing PLDM PDR header for unpacked value
+ *  Refer to: DSP0248_1.2.0: 28.1 Table 75
+ */
+struct pldm_value_pdr_hdr {
+	uint32_t record_handle;
+	uint8_t version;
+	uint8_t type;
+	uint16_t record_change_num;
+	uint16_t length;
+};
+
+/** @struct pldm_numeric_sensor_value_pdr
+ *
+ *  Structure representing PLDM Numeric Sensor PDR for unpacked value
+ *  Refer to: DSP0248_1.2.0: 28.4 Table 78
+ */
+struct pldm_numeric_sensor_value_pdr {
+	struct pldm_value_pdr_hdr hdr;
+	uint16_t terminus_handle;
+	uint16_t sensor_id;
+	uint16_t entity_type;
+	uint16_t entity_instance_num;
+	uint16_t container_id;
+	uint8_t sensor_init;
+	bool8_t sensor_auxiliary_names_pdr;
+	uint8_t base_unit;
+	int8_t unit_modifier;
+	uint8_t rate_unit;
+	uint8_t base_oem_unit_handle;
+	uint8_t aux_unit;
+	int8_t aux_unit_modifier;
+	uint8_t aux_rate_unit;
+	uint8_t rel;
+	uint8_t aux_oem_unit_handle;
+	bool8_t is_linear;
+	uint8_t sensor_data_size;
+	real32_t resolution;
+	real32_t offset;
+	uint16_t accuracy;
+	uint8_t plus_tolerance;
+	uint8_t minus_tolerance;
+	union_sensor_data_size hysteresis;
+	bitfield8_t supported_thresholds;
+	bitfield8_t threshold_and_hysteresis_volatility;
+	real32_t state_transition_interval;
+	real32_t update_interval;
+	union_sensor_data_size max_readable;
+	union_sensor_data_size min_readable;
+	uint8_t range_field_format;
+	bitfield8_t range_field_support;
+	union_range_field_format nominal_value;
+	union_range_field_format normal_max;
+	union_range_field_format normal_min;
+	union_range_field_format warning_high;
+	union_range_field_format warning_low;
+	union_range_field_format critical_high;
+	union_range_field_format critical_low;
+	union_range_field_format fatal_high;
+	union_range_field_format fatal_low;
+};
+
 /** @struct state_effecter_possible_states
  *
  *  Structure representing state enums for state effecter
@@ -1646,6 +1751,16 @@
 			       uint8_t *sensor_data_size,
 			       uint32_t *present_reading);
 
+/** @brief Decode Numeric Sensor Pdr data
+ *
+ *  @param[in] pdr_data - pdr data for numeric sensor
+ *  @param[in] pdr_data_length - Length of pdr data
+ *  @param[out] pdr_value - unpacked numeric sensor PDR struct
+ */
+int decode_numeric_sensor_pdr_data(
+    const void *pdr_data, size_t pdr_data_length,
+    struct pldm_numeric_sensor_value_pdr *pdr_value);
+
 /* GetNumericEffecterValue */
 
 /** @brief Create a PLDM request message for GetNumericEffecterValue
diff --git a/src/msgbuf/platform.h b/src/msgbuf/platform.h
new file mode 100644
index 0000000..c10dc45
--- /dev/null
+++ b/src/msgbuf/platform.h
@@ -0,0 +1,76 @@
+#ifndef PLDM_MSGBUF_PLATFORM_H
+#define PLDM_MSGBUF_PLATFORM_H
+
+#include "../msgbuf.h"
+#include <libpldm/base.h>
+#include <libpldm/platform.h>
+
+static inline int
+pldm_msgbuf_extract_value_pdr_hdr(struct pldm_msgbuf *ctx,
+				  struct pldm_value_pdr_hdr *hdr)
+{
+	pldm_msgbuf_extract(ctx, &hdr->record_handle);
+	pldm_msgbuf_extract(ctx, &hdr->version);
+	pldm_msgbuf_extract(ctx, &hdr->type);
+	pldm_msgbuf_extract(ctx, &hdr->record_change_num);
+	pldm_msgbuf_extract(ctx, &hdr->length);
+
+	return pldm_msgbuf_validate(ctx);
+}
+
+/*
+ * We use __attribute__((always_inline)) below so the compiler has visibility of
+ * the switch() at the call site. It is often the case that the size of multiple
+ * fields depends on the tag. Inlining thus gives the compiler visibility to
+ * hoist one tag-based code-path condition to cover all invocations.
+ */
+
+__attribute__((always_inline)) static inline int
+pldm_msgbuf_extract_sensor_data(struct pldm_msgbuf *ctx,
+				enum pldm_sensor_readings_data_type tag,
+				union_sensor_data_size *dst)
+{
+	switch (tag) {
+	case PLDM_SENSOR_DATA_SIZE_UINT8:
+		return pldm_msgbuf_extract(ctx, &dst->value_u8);
+	case PLDM_SENSOR_DATA_SIZE_SINT8:
+		return pldm_msgbuf_extract(ctx, &dst->value_s8);
+	case PLDM_SENSOR_DATA_SIZE_UINT16:
+		return pldm_msgbuf_extract(ctx, &dst->value_u16);
+	case PLDM_SENSOR_DATA_SIZE_SINT16:
+		return pldm_msgbuf_extract(ctx, &dst->value_s16);
+	case PLDM_SENSOR_DATA_SIZE_UINT32:
+		return pldm_msgbuf_extract(ctx, &dst->value_u32);
+	case PLDM_SENSOR_DATA_SIZE_SINT32:
+		return pldm_msgbuf_extract(ctx, &dst->value_s32);
+	}
+
+	return -PLDM_ERROR_INVALID_DATA;
+}
+
+__attribute__((always_inline)) static inline int
+pldm_msgbuf_extract_range_field_format(struct pldm_msgbuf *ctx,
+				       enum pldm_range_field_format tag,
+				       union_range_field_format *dst)
+{
+	switch (tag) {
+	case PLDM_RANGE_FIELD_FORMAT_UINT8:
+		return pldm_msgbuf_extract(ctx, &dst->value_u8);
+	case PLDM_RANGE_FIELD_FORMAT_SINT8:
+		return pldm_msgbuf_extract(ctx, &dst->value_s8);
+	case PLDM_RANGE_FIELD_FORMAT_UINT16:
+		return pldm_msgbuf_extract(ctx, &dst->value_u16);
+	case PLDM_RANGE_FIELD_FORMAT_SINT16:
+		return pldm_msgbuf_extract(ctx, &dst->value_s16);
+	case PLDM_RANGE_FIELD_FORMAT_UINT32:
+		return pldm_msgbuf_extract(ctx, &dst->value_u32);
+	case PLDM_RANGE_FIELD_FORMAT_SINT32:
+		return pldm_msgbuf_extract(ctx, &dst->value_s32);
+	case PLDM_RANGE_FIELD_FORMAT_REAL32:
+		return pldm_msgbuf_extract(ctx, &dst->value_f32);
+	}
+
+	return -PLDM_ERROR_INVALID_DATA;
+}
+
+#endif
diff --git a/src/platform.c b/src/platform.c
index a805416..0abd6e8 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -1,10 +1,25 @@
+#include "msgbuf/platform.h"
 #include "base.h"
+#include "msgbuf.h"
+#include "platform.h"
 #include "pldm_types.h"
 #include <endian.h>
 #include <stdint.h>
 #include <string.h>
 
-#include "platform.h"
+static int pldm_platform_pdr_hdr_validate(struct pldm_value_pdr_hdr *ctx,
+					  size_t lower, size_t upper)
+{
+	if (ctx->length + sizeof(*ctx) < lower) {
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	if (ctx->length > upper) {
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	return PLDM_SUCCESS;
+}
 
 int encode_state_effecter_pdr(
     struct pldm_state_effecter_pdr *const effecter,
@@ -1235,6 +1250,107 @@
 	return PLDM_SUCCESS;
 }
 
+#define PLDM_NUMERIC_SENSOR_VALUE_PDR_MIN_SIZE 69
+int decode_numeric_sensor_pdr_data(
+    const void *pdr_data, size_t pdr_data_length,
+    struct pldm_numeric_sensor_value_pdr *pdr_value)
+{
+	struct pldm_msgbuf _buf;
+	struct pldm_msgbuf *buf = &_buf;
+	int rc;
+
+	rc = pldm_msgbuf_init(buf, PLDM_NUMERIC_SENSOR_VALUE_PDR_MIN_SIZE,
+			      pdr_data, pdr_data_length);
+	if (rc) {
+		return rc;
+	}
+
+	rc = pldm_msgbuf_extract_value_pdr_hdr(buf, &pdr_value->hdr);
+	if (rc) {
+		return rc;
+	}
+
+	rc = pldm_platform_pdr_hdr_validate(
+	    &pdr_value->hdr, PLDM_NUMERIC_SENSOR_VALUE_PDR_MIN_SIZE,
+	    pdr_data_length);
+	if (rc) {
+		return rc;
+	}
+
+	pldm_msgbuf_extract(buf, &pdr_value->terminus_handle);
+	pldm_msgbuf_extract(buf, &pdr_value->sensor_id);
+	pldm_msgbuf_extract(buf, &pdr_value->entity_type);
+	pldm_msgbuf_extract(buf, &pdr_value->entity_instance_num);
+	pldm_msgbuf_extract(buf, &pdr_value->container_id);
+	pldm_msgbuf_extract(buf, &pdr_value->sensor_init);
+	pldm_msgbuf_extract(buf, &pdr_value->sensor_auxiliary_names_pdr);
+	pldm_msgbuf_extract(buf, &pdr_value->base_unit);
+	pldm_msgbuf_extract(buf, &pdr_value->unit_modifier);
+	pldm_msgbuf_extract(buf, &pdr_value->rate_unit);
+	pldm_msgbuf_extract(buf, &pdr_value->base_oem_unit_handle);
+	pldm_msgbuf_extract(buf, &pdr_value->aux_unit);
+	pldm_msgbuf_extract(buf, &pdr_value->aux_unit_modifier);
+	pldm_msgbuf_extract(buf, &pdr_value->aux_rate_unit);
+	pldm_msgbuf_extract(buf, &pdr_value->rel);
+	pldm_msgbuf_extract(buf, &pdr_value->aux_oem_unit_handle);
+	pldm_msgbuf_extract(buf, &pdr_value->is_linear);
+
+	rc = pldm_msgbuf_extract(buf, &pdr_value->sensor_data_size);
+	if (rc) {
+		return rc;
+	}
+	if (pdr_value->sensor_data_size > PLDM_SENSOR_DATA_SIZE_MAX) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	pldm_msgbuf_extract(buf, &pdr_value->resolution);
+	pldm_msgbuf_extract(buf, &pdr_value->offset);
+	pldm_msgbuf_extract(buf, &pdr_value->accuracy);
+	pldm_msgbuf_extract(buf, &pdr_value->plus_tolerance);
+	pldm_msgbuf_extract(buf, &pdr_value->minus_tolerance);
+	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
+					&pdr_value->hysteresis);
+	pldm_msgbuf_extract(buf, &pdr_value->supported_thresholds.byte);
+	pldm_msgbuf_extract(
+	    buf, &pdr_value->threshold_and_hysteresis_volatility.byte);
+	pldm_msgbuf_extract(buf, &pdr_value->state_transition_interval);
+	pldm_msgbuf_extract(buf, &pdr_value->update_interval);
+	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
+					&pdr_value->max_readable);
+	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
+					&pdr_value->min_readable);
+
+	rc = pldm_msgbuf_extract(buf, &pdr_value->range_field_format);
+	if (rc) {
+		return rc;
+	}
+	if (pdr_value->range_field_format > PLDM_RANGE_FIELD_FORMAT_MAX) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	pldm_msgbuf_extract(buf, &pdr_value->range_field_support.byte);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->nominal_value);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->normal_max);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->normal_min);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->warning_high);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->warning_low);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->critical_high);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->critical_low);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->fatal_high);
+	pldm_msgbuf_extract_range_field_format(
+	    buf, pdr_value->range_field_format, &pdr_value->fatal_low);
+
+	return pldm_msgbuf_destroy(buf);
+}
+
 int encode_get_numeric_effecter_value_req(uint8_t instance_id,
 					  uint16_t effecter_id,
 					  struct pldm_msg *msg)
diff --git a/tests/libpldm_platform_test.cpp b/tests/libpldm_platform_test.cpp
index d346067..975bd74 100644
--- a/tests/libpldm_platform_test.cpp
+++ b/tests/libpldm_platform_test.cpp
@@ -6,6 +6,7 @@
 #include <vector>
 
 #include "libpldm/base.h"
+#include "libpldm/entity.h"
 #include "libpldm/platform.h"
 #include "pldm_types.h"
 
@@ -2435,3 +2436,892 @@
         &retheartbeatTimer);
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
 }
+
+TEST(decodeNumericSensorPdrData, Uint8Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        1,
+        0,                           // containerID=1
+        PLDM_NO_INIT,                // sensorInit
+        false,                       // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,  // baseUint(2)=degrees C
+        0,                           // unitModifier
+        0,                           // rateUnit
+        0,                           // baseOEMUnitHandle
+        0,                           // auxUnit
+        0,                           // auxUnitModifier
+        0,                           // auxRateUnit
+        0,                           // rel
+        0,                           // auxOEMUnitHandle
+        true,                        // isLinear
+        PLDM_SENSOR_DATA_SIZE_UINT8, // sensorDataSize
+        0,
+        0,
+        0xc0,
+        0x3f, // resolution=1.5
+        0,
+        0,
+        0x80,
+        0x3f, // offset=1.0
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3, // hysteresis = 3
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f,                          // updateInverval=1.0
+        255,                           // maxReadable
+        0,                             // minReadable
+        PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
+        0,                             // rangeFieldsupport
+        50,                            // nominalValue = 50
+        60,                            // normalMax = 60
+        40,                            // normalMin = 40
+        70,                            // warningHigh = 70
+        30,                            // warningLow = 30
+        80,                            // criticalHigh = 80
+        20,                            // criticalLow = 20
+        90,                            // fatalHigh = 90
+        10                             // fatalLow = 10
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+    EXPECT_EQ(1, decodedPdr.hdr.record_handle);
+    EXPECT_EQ(1, decodedPdr.hdr.version);
+    EXPECT_EQ(PLDM_NUMERIC_SENSOR_PDR, decodedPdr.hdr.type);
+    EXPECT_EQ(0, decodedPdr.hdr.record_change_num);
+    EXPECT_EQ(PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH, decodedPdr.hdr.length);
+    EXPECT_EQ(1, decodedPdr.sensor_id);
+    EXPECT_EQ(PLDM_ENTITY_POWER_SUPPLY, decodedPdr.entity_type);
+    EXPECT_EQ(1, decodedPdr.entity_instance_num);
+    EXPECT_EQ(1, decodedPdr.container_id);
+    EXPECT_EQ(PLDM_NO_INIT, decodedPdr.sensor_init);
+    EXPECT_EQ(false, decodedPdr.sensor_auxiliary_names_pdr);
+    EXPECT_EQ(PLDM_SENSOR_UNIT_DEGRESS_C, decodedPdr.base_unit);
+    EXPECT_EQ(0, decodedPdr.unit_modifier);
+    EXPECT_EQ(0, decodedPdr.rate_unit);
+    EXPECT_EQ(0, decodedPdr.base_oem_unit_handle);
+    EXPECT_EQ(0, decodedPdr.aux_unit);
+    EXPECT_EQ(0, decodedPdr.aux_unit_modifier);
+    EXPECT_EQ(0, decodedPdr.aux_rate_unit);
+    EXPECT_EQ(0, decodedPdr.rel);
+    EXPECT_EQ(0, decodedPdr.aux_oem_unit_handle);
+    EXPECT_EQ(true, decodedPdr.is_linear);
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_UINT8, decodedPdr.sensor_data_size);
+    EXPECT_FLOAT_EQ(1.5f, decodedPdr.resolution);
+    EXPECT_FLOAT_EQ(1.0f, decodedPdr.offset);
+    EXPECT_EQ(0, decodedPdr.accuracy);
+    EXPECT_EQ(0, decodedPdr.plus_tolerance);
+    EXPECT_EQ(0, decodedPdr.minus_tolerance);
+    EXPECT_EQ(3, decodedPdr.hysteresis.value_u8);
+    EXPECT_EQ(0, decodedPdr.supported_thresholds.byte);
+    EXPECT_EQ(0, decodedPdr.threshold_and_hysteresis_volatility.byte);
+    EXPECT_FLOAT_EQ(1.0f, decodedPdr.state_transition_interval);
+    EXPECT_FLOAT_EQ(1.0f, decodedPdr.update_interval);
+    EXPECT_EQ(255, decodedPdr.max_readable.value_u8);
+    EXPECT_EQ(0, decodedPdr.min_readable.value_u8);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_UINT8, decodedPdr.range_field_format);
+    EXPECT_EQ(0, decodedPdr.range_field_support.byte);
+    EXPECT_EQ(50, decodedPdr.nominal_value.value_u8);
+    EXPECT_EQ(60, decodedPdr.normal_max.value_u8);
+    EXPECT_EQ(40, decodedPdr.normal_min.value_u8);
+    EXPECT_EQ(70, decodedPdr.warning_high.value_u8);
+    EXPECT_EQ(30, decodedPdr.warning_low.value_u8);
+    EXPECT_EQ(80, decodedPdr.critical_high.value_u8);
+    EXPECT_EQ(20, decodedPdr.critical_low.value_u8);
+    EXPECT_EQ(90, decodedPdr.fatal_high.value_u8);
+    EXPECT_EQ(10, decodedPdr.fatal_low.value_u8);
+}
+
+TEST(decodeNumericSensorPdrData, Sint8Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                           // containerID=1
+        PLDM_NO_INIT,                  // sensorInit
+        false,                         // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,    // baseUint(2)=degrees C
+        0,                             // unitModifier
+        0,                             // rateUnit
+        0,                             // baseOEMUnitHandle
+        0,                             // auxUnit
+        0,                             // auxUnitModifier
+        0,                             // auxRateUnit
+        0,                             // rel
+        0,                             // auxOEMUnitHandle
+        true,                          // isLinear
+        PLDM_RANGE_FIELD_FORMAT_SINT8, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3, // hysteresis = 3
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f,                          // updateInverval=1.0
+        0x64,                          // maxReadable = 100
+        0x9c,                          // minReadable = -100
+        PLDM_RANGE_FIELD_FORMAT_SINT8, // rangeFieldFormat
+        0,                             // rangeFieldsupport
+        0,                             // nominalValue = 0
+        5,                             // normalMax = 5
+        0xfb,                          // normalMin = -5
+        10,                            // warningHigh = 10
+        0xf6,                          // warningLow = -10
+        20,                            // criticalHigh = 20
+        0xec,                          // criticalLow = -20
+        30,                            // fatalHigh = 30
+        0xe2                           // fatalLow = -30
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_SINT8, decodedPdr.sensor_data_size);
+    EXPECT_EQ(100, decodedPdr.max_readable.value_s8);
+    EXPECT_EQ(-100, decodedPdr.min_readable.value_s8);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_SINT8, decodedPdr.range_field_format);
+    EXPECT_EQ(0, decodedPdr.nominal_value.value_s8);
+    EXPECT_EQ(5, decodedPdr.normal_max.value_s8);
+    EXPECT_EQ(-5, decodedPdr.normal_min.value_s8);
+    EXPECT_EQ(10, decodedPdr.warning_high.value_s8);
+    EXPECT_EQ(-10, decodedPdr.warning_low.value_s8);
+    EXPECT_EQ(20, decodedPdr.critical_high.value_s8);
+    EXPECT_EQ(-20, decodedPdr.critical_low.value_s8);
+    EXPECT_EQ(30, decodedPdr.fatal_high.value_s8);
+    EXPECT_EQ(-30, decodedPdr.fatal_low.value_s8);
+}
+
+TEST(decodeNumericSensorPdrData, Uint16Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH * 2 +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH * 2,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                          // containerID=1
+        PLDM_NO_INIT,                 // sensorInit
+        false,                        // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,   // baseUint(2)=degrees C
+        0,                            // unitModifier
+        0,                            // rateUnit
+        0,                            // baseOEMUnitHandle
+        0,                            // auxUnit
+        0,                            // auxUnitModifier
+        0,                            // auxRateUnit
+        0,                            // rel
+        0,                            // auxOEMUnitHandle
+        true,                         // isLinear
+        PLDM_SENSOR_DATA_SIZE_UINT16, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3,
+        0, // hysteresis = 3
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f, // updateInverval=1.0
+        0,
+        0x10, // maxReadable = 4096
+        0,
+        0,                              // minReadable = 0
+        PLDM_RANGE_FIELD_FORMAT_UINT16, // rangeFieldFormat
+        0,                              // rangeFieldsupport
+        0x88,
+        0x13, // nominalValue = 5,000
+        0x70,
+        0x17, // normalMax = 6,000
+        0xa0,
+        0x0f, // normalMin = 4,000
+        0x58,
+        0x1b, // warningHigh = 7,000
+        0xb8,
+        0x0b, // warningLow = 3,000
+        0x40,
+        0x1f, // criticalHigh = 8,000
+        0xd0,
+        0x07, // criticalLow = 2,000
+        0x28,
+        0x23, // fatalHigh = 9,000
+        0xe8,
+        0x03 // fatalLow = 1,000
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_UINT16, decodedPdr.sensor_data_size);
+    EXPECT_EQ(4096, decodedPdr.max_readable.value_u16);
+    EXPECT_EQ(0, decodedPdr.min_readable.value_u16);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_UINT16, decodedPdr.range_field_format);
+    EXPECT_EQ(5000, decodedPdr.nominal_value.value_u16);
+    EXPECT_EQ(6000, decodedPdr.normal_max.value_u16);
+    EXPECT_EQ(4000, decodedPdr.normal_min.value_u16);
+    EXPECT_EQ(7000, decodedPdr.warning_high.value_u16);
+    EXPECT_EQ(3000, decodedPdr.warning_low.value_u16);
+    EXPECT_EQ(8000, decodedPdr.critical_high.value_u16);
+    EXPECT_EQ(2000, decodedPdr.critical_low.value_u16);
+    EXPECT_EQ(9000, decodedPdr.fatal_high.value_u16);
+    EXPECT_EQ(1000, decodedPdr.fatal_low.value_u16);
+}
+
+TEST(decodeNumericSensorPdrData, Sint16Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH * 2 +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH * 2,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                          // containerID=1
+        PLDM_NO_INIT,                 // sensorInit
+        false,                        // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,   // baseUint(2)=degrees C
+        0,                            // unitModifier
+        0,                            // rateUnit
+        0,                            // baseOEMUnitHandle
+        0,                            // auxUnit
+        0,                            // auxUnitModifier
+        0,                            // auxRateUnit
+        0,                            // rel
+        0,                            // auxOEMUnitHandle
+        true,                         // isLinear
+        PLDM_SENSOR_DATA_SIZE_SINT16, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3,
+        0, // hysteresis
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f, // updateInverval=1.0
+        0xe8,
+        0x03, // maxReadable = 1000
+        0x18,
+        0xfc,                           // minReadable = -1000
+        PLDM_RANGE_FIELD_FORMAT_SINT16, // rangeFieldFormat
+        0,                              // rangeFieldsupport
+        0,
+        0, // nominalValue = 0
+        0xf4,
+        0x01, // normalMax = 500
+        0x0c,
+        0xfe, // normalMin = -500
+        0xe8,
+        0x03, // warningHigh = 1,000
+        0x18,
+        0xfc, // warningLow = -1,000
+        0xd0,
+        0x07, // criticalHigh = 2,000
+        0x30,
+        0xf8, // criticalLow = -2,000
+        0xb8,
+        0x0b, // fatalHigh = 3,000
+        0x48,
+        0xf4 // fatalLow = -3,000
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_SINT16, decodedPdr.sensor_data_size);
+    EXPECT_EQ(1000, decodedPdr.max_readable.value_s16);
+    EXPECT_EQ(-1000, decodedPdr.min_readable.value_s16);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_SINT16, decodedPdr.range_field_format);
+    EXPECT_EQ(0, decodedPdr.nominal_value.value_s16);
+    EXPECT_EQ(500, decodedPdr.normal_max.value_s16);
+    EXPECT_EQ(-500, decodedPdr.normal_min.value_s16);
+    EXPECT_EQ(1000, decodedPdr.warning_high.value_s16);
+    EXPECT_EQ(-1000, decodedPdr.warning_low.value_s16);
+    EXPECT_EQ(2000, decodedPdr.critical_high.value_s16);
+    EXPECT_EQ(-2000, decodedPdr.critical_low.value_s16);
+    EXPECT_EQ(3000, decodedPdr.fatal_high.value_s16);
+    EXPECT_EQ(-3000, decodedPdr.fatal_low.value_s16);
+}
+
+TEST(decodeNumericSensorPdrData, Uint32Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH * 4 +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH * 4,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                          // containerID=1
+        PLDM_NO_INIT,                 // sensorInit
+        false,                        // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,   // baseUint(2)=degrees C
+        0,                            // unitModifier
+        0,                            // rateUnit
+        0,                            // baseOEMUnitHandle
+        0,                            // auxUnit
+        0,                            // auxUnitModifier
+        0,                            // auxRateUnit
+        0,                            // rel
+        0,                            // auxOEMUnitHandle
+        true,                         // isLinear
+        PLDM_SENSOR_DATA_SIZE_UINT32, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3,
+        0,
+        0,
+        0, // hysteresis
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f, // updateInverval=1.0
+        0,
+        0x10,
+        0,
+        0, // maxReadable = 4096
+        0,
+        0,
+        0,
+        0,                              // minReadable = 0
+        PLDM_RANGE_FIELD_FORMAT_UINT32, // rangeFieldFormat
+        0,                              // rangeFieldsupport
+        0x40,
+        0x4b,
+        0x4c,
+        0x00, // nominalValue = 5,000,000
+        0x80,
+        0x8d,
+        0x5b,
+        0x00, // normalMax = 6,000,000
+        0x00,
+        0x09,
+        0x3d,
+        0x00, // normalMin = 4,000,000
+        0xc0,
+        0xcf,
+        0x6a,
+        0x00, // warningHigh = 7,000,000
+        0xc0,
+        0xc6,
+        0x2d,
+        0x00, // warningLow = 3,000,000
+        0x00,
+        0x12,
+        0x7a,
+        0x00, // criticalHigh = 8,000,000
+        0x80,
+        0x84,
+        0x1e,
+        0x00, // criticalLow = 2,000,000
+        0x40,
+        0x54,
+        0x89,
+        0x00, // fatalHigh = 9,000,000
+        0x40,
+        0x42,
+        0x0f,
+        0x00 // fatalLow = 1,000,000
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_UINT32, decodedPdr.sensor_data_size);
+    EXPECT_EQ(4096, decodedPdr.max_readable.value_u32);
+    EXPECT_EQ(0, decodedPdr.min_readable.value_u32);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_UINT32, decodedPdr.range_field_format);
+    EXPECT_EQ(5000000, decodedPdr.nominal_value.value_u32);
+    EXPECT_EQ(6000000, decodedPdr.normal_max.value_u32);
+    EXPECT_EQ(4000000, decodedPdr.normal_min.value_u32);
+    EXPECT_EQ(7000000, decodedPdr.warning_high.value_u32);
+    EXPECT_EQ(3000000, decodedPdr.warning_low.value_u32);
+    EXPECT_EQ(8000000, decodedPdr.critical_high.value_u32);
+    EXPECT_EQ(2000000, decodedPdr.critical_low.value_u32);
+    EXPECT_EQ(9000000, decodedPdr.fatal_high.value_u32);
+    EXPECT_EQ(1000000, decodedPdr.fatal_low.value_u32);
+}
+
+TEST(decodeNumericSensorPdrData, Sint32Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH * 4 +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH * 4,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                          // containerID=1
+        PLDM_NO_INIT,                 // sensorInit
+        false,                        // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,   // baseUint(2)=degrees C
+        0,                            // unitModifier
+        0,                            // rateUnit
+        0,                            // baseOEMUnitHandle
+        0,                            // auxUnit
+        0,                            // auxUnitModifier
+        0,                            // auxRateUnit
+        0,                            // rel
+        0,                            // auxOEMUnitHandle
+        true,                         // isLinear
+        PLDM_SENSOR_DATA_SIZE_SINT32, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3,
+        0,
+        0,
+        0, // hysteresis
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f, // updateInverval=1.0
+        0xa0,
+        0x86,
+        0x01,
+        0x00, // maxReadable = 100000
+        0x60,
+        0x79,
+        0xfe,
+        0xff,                           // minReadable = -10000
+        PLDM_RANGE_FIELD_FORMAT_SINT32, // rangeFieldFormat
+        0,                              // rangeFieldsupport
+        0,
+        0,
+        0,
+        0, // nominalValue = 0
+        0x20,
+        0xa1,
+        0x07,
+        0x00, // normalMax = 500,000
+        0xe0,
+        0x5e,
+        0xf8,
+        0xff, // normalMin = -500,000
+        0x40,
+        0x42,
+        0x0f,
+        0x00, // warningHigh = 1,000,000
+        0xc0,
+        0xbd,
+        0xf0,
+        0xff, // warningLow = -1,000,000
+        0x80,
+        0x84,
+        0x1e,
+        0x00, // criticalHigh = 2,000,000
+        0x80,
+        0x7b,
+        0xe1,
+        0xff, // criticalLow = -2,000,000
+        0xc0,
+        0xc6,
+        0x2d,
+        0x00, // fatalHigh = 3,000,000
+        0x40,
+        0x39,
+        0xd2,
+        0xff // fatalLow = -3,000,000
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_SINT32, decodedPdr.sensor_data_size);
+    EXPECT_EQ(100000, decodedPdr.max_readable.value_s32);
+    EXPECT_EQ(-100000, decodedPdr.min_readable.value_s32);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_SINT32, decodedPdr.range_field_format);
+    EXPECT_EQ(0, decodedPdr.nominal_value.value_s32);
+    EXPECT_EQ(500000, decodedPdr.normal_max.value_s32);
+    EXPECT_EQ(-500000, decodedPdr.normal_min.value_s32);
+    EXPECT_EQ(1000000, decodedPdr.warning_high.value_s32);
+    EXPECT_EQ(-1000000, decodedPdr.warning_low.value_s32);
+    EXPECT_EQ(2000000, decodedPdr.critical_high.value_s32);
+    EXPECT_EQ(-2000000, decodedPdr.critical_low.value_s32);
+    EXPECT_EQ(3000000, decodedPdr.fatal_high.value_s32);
+    EXPECT_EQ(-3000000, decodedPdr.fatal_low.value_s32);
+}
+
+TEST(decodeNumericSensorPdrData, Real32Test)
+{
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH * 4 +
+            PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH * 4,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                          // containerID=1
+        PLDM_NO_INIT,                 // sensorInit
+        false,                        // sensorAuxiliaryNamesPDR
+        PLDM_SENSOR_UNIT_DEGRESS_C,   // baseUint(2)=degrees C
+        0,                            // unitModifier
+        0,                            // rateUnit
+        0,                            // baseOEMUnitHandle
+        0,                            // auxUnit
+        0,                            // auxUnitModifier
+        0,                            // auxRateUnit
+        0,                            // rel
+        0,                            // auxOEMUnitHandle
+        true,                         // isLinear
+        PLDM_SENSOR_DATA_SIZE_SINT32, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0, // plusTolerance
+        0, // minusTolerance
+        3,
+        0,
+        0,
+        0, // hysteresis
+        0, // supportedThresholds
+        0, // thresholdAndHysteresisVolatility
+        0,
+        0,
+        0x80,
+        0x3f, // stateTransistionInterval=1.0
+        0,
+        0,
+        0x80,
+        0x3f, // updateInverval=1.0
+        0xa0,
+        0x86,
+        0x01,
+        0x00, // maxReadable = 100000
+        0x60,
+        0x79,
+        0xfe,
+        0xff,                           // minReadable = -10000
+        PLDM_RANGE_FIELD_FORMAT_REAL32, // rangeFieldFormat
+        0,                              // rangeFieldsupport
+        0,
+        0,
+        0,
+        0, // nominalValue = 0.0
+        0x33,
+        0x33,
+        0x48,
+        0x42, // normalMax = 50.05
+        0x33,
+        0x33,
+        0x48,
+        0xc2, // normalMin = -50.05
+        0x83,
+        0x00,
+        0xc8,
+        0x42, // warningHigh = 100.001
+        0x83,
+        0x00,
+        0xc8,
+        0xc2, // warningLow = -100.001
+        0x83,
+        0x00,
+        0x48,
+        0x43, // criticalHigh = 200.002
+        0x83,
+        0x00,
+        0x48,
+        0xc3, // criticalLow = -200.002
+        0x62,
+        0x00,
+        0x96,
+        0x43, // fatalHigh = 300.003
+        0x62,
+        0x00,
+        0x96,
+        0xc3 // fatalLow = -300.003
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    auto rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(PLDM_SUCCESS, rc);
+
+    EXPECT_EQ(PLDM_SENSOR_DATA_SIZE_SINT32, decodedPdr.sensor_data_size);
+    EXPECT_EQ(100000, decodedPdr.max_readable.value_s32);
+    EXPECT_EQ(-100000, decodedPdr.min_readable.value_s32);
+    EXPECT_EQ(PLDM_RANGE_FIELD_FORMAT_REAL32, decodedPdr.range_field_format);
+    EXPECT_FLOAT_EQ(0, decodedPdr.nominal_value.value_f32);
+    EXPECT_FLOAT_EQ(50.05f, decodedPdr.normal_max.value_f32);
+    EXPECT_FLOAT_EQ(-50.05f, decodedPdr.normal_min.value_f32);
+    EXPECT_FLOAT_EQ(100.001f, decodedPdr.warning_high.value_f32);
+    EXPECT_FLOAT_EQ(-100.001f, decodedPdr.warning_low.value_f32);
+    EXPECT_FLOAT_EQ(200.002f, decodedPdr.critical_high.value_f32);
+    EXPECT_FLOAT_EQ(-200.002f, decodedPdr.critical_low.value_f32);
+    EXPECT_FLOAT_EQ(300.003f, decodedPdr.fatal_high.value_f32);
+    EXPECT_FLOAT_EQ(-300.003f, decodedPdr.fatal_low.value_f32);
+}
+
+TEST(decodeNumericSensorPdrDataDeathTest, InvalidSizeTest)
+{
+    // A corrupted PDR. The data after plusTolerance missed.
+    std::vector<uint8_t> pdr1{
+        0x1,
+        0x0,
+        0x0,
+        0x0,                     // record handle
+        0x1,                     // PDRHeaderVersion
+        PLDM_NUMERIC_SENSOR_PDR, // PDRType
+        0x0,
+        0x0, // recordChangeNumber
+        PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH,
+        0, // dataLength
+        0,
+        0, // PLDMTerminusHandle
+        0x1,
+        0x0, // sensorID=1
+        PLDM_ENTITY_POWER_SUPPLY,
+        0, // entityType=Power Supply(120)
+        1,
+        0, // entityInstanceNumber
+        0x1,
+        0x0,                         // containerID=1
+        PLDM_NO_INIT,                // sensorInit
+        false,                       // sensorAuxiliaryNamesPDR
+        2,                           // baseUint(2)=degrees C
+        0,                           // unitModifier
+        0,                           // rateUnit
+        0,                           // baseOEMUnitHandle
+        0,                           // auxUnit
+        0,                           // auxUnitModifier
+        0,                           // auxRateUnit
+        0,                           // rel
+        0,                           // auxOEMUnitHandle
+        true,                        // isLinear
+        PLDM_SENSOR_DATA_SIZE_UINT8, // sensorDataSize
+        0,
+        0,
+        0,
+        0, // resolution
+        0,
+        0,
+        0,
+        0, // offset
+        0,
+        0, // accuracy
+        0  // plusTolerance
+    };
+
+    struct pldm_numeric_sensor_value_pdr decodedPdr;
+    int rc =
+        decode_numeric_sensor_pdr_data(pdr1.data(), pdr1.size(), &decodedPdr);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}