Update min and max values to thresholds if needed

In an incorrect config, thresholds may be outside of
min and max, which would cause incorrect scaling. Correct
this by changing max and min to be the outliers of min/max
and thresholds. Also make it so that the max value will be
an acceptable value by scaling up the mvalue.

Tested: ipmi sensor list with bad scaled sensor works,
unit-test added to verfiy as well

Change-Id: I934efc87b09cd131e8b85a30697b3167437de4d4
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/src/sensorcommands.cpp b/src/sensorcommands.cpp
index abc5609..50a640a 100644
--- a/src/sensorcommands.cpp
+++ b/src/sensorcommands.cpp
@@ -143,22 +143,66 @@
         }
     });
 
-static void
-    getSensorMaxMin(const std::map<std::string, DbusVariant> &sensorPropertyMap,
-                    double &max, double &min)
+static void getSensorMaxMin(const SensorMap &sensorMap, double &max,
+                            double &min)
 {
-    auto maxMap = sensorPropertyMap.find("MaxValue");
-    auto minMap = sensorPropertyMap.find("MinValue");
     max = 127;
     min = -128;
 
-    if (maxMap != sensorPropertyMap.end())
+    auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
+    auto critical =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+    auto warning =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+
+    if (sensorObject != sensorMap.end())
     {
-        max = variant_ns::visit(VariantToDoubleVisitor(), maxMap->second);
+        auto maxMap = sensorObject->second.find("MaxValue");
+        auto minMap = sensorObject->second.find("MinValue");
+
+        if (maxMap != sensorObject->second.end())
+        {
+            max = variant_ns::visit(VariantToDoubleVisitor(), maxMap->second);
+        }
+        if (minMap != sensorObject->second.end())
+        {
+            min = variant_ns::visit(VariantToDoubleVisitor(), minMap->second);
+        }
     }
-    if (minMap != sensorPropertyMap.end())
+    if (critical != sensorMap.end())
     {
-        min = variant_ns::visit(VariantToDoubleVisitor(), minMap->second);
+        auto lower = critical->second.find("CriticalLow");
+        auto upper = critical->second.find("CriticalHigh");
+        if (lower != critical->second.end())
+        {
+            double value =
+                variant_ns::visit(VariantToDoubleVisitor(), lower->second);
+            min = std::min(value, min);
+        }
+        if (upper != critical->second.end())
+        {
+            double value =
+                variant_ns::visit(VariantToDoubleVisitor(), upper->second);
+            max = std::max(value, max);
+        }
+    }
+    if (warning != sensorMap.end())
+    {
+
+        auto lower = warning->second.find("WarningLow");
+        auto upper = warning->second.find("WarningHigh");
+        if (lower != warning->second.end())
+        {
+            double value =
+                variant_ns::visit(VariantToDoubleVisitor(), lower->second);
+            min = std::min(value, min);
+        }
+        if (upper != warning->second.end())
+        {
+            double value =
+                variant_ns::visit(VariantToDoubleVisitor(), upper->second);
+            max = std::max(value, max);
+        }
     }
 }
 
@@ -322,7 +366,7 @@
 
     double max;
     double min;
-    getSensorMaxMin(sensorObject->second, max, min);
+    getSensorMaxMin(sensorMap, max, min);
 
     int16_t mValue = 0;
     int16_t bValue = 0;
@@ -446,15 +490,9 @@
         return IPMI_CC_RESPONSE_ERROR;
     }
 
-    auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
-
-    if (sensorObject == sensorMap.end())
-    {
-        return IPMI_CC_RESPONSE_ERROR;
-    }
     double max = 0;
     double min = 0;
-    getSensorMaxMin(sensorObject->second, max, min);
+    getSensorMaxMin(sensorMap, max, min);
 
     int16_t mValue = 0;
     int16_t bValue = 0;
@@ -584,7 +622,7 @@
 
         double max;
         double min;
-        getSensorMaxMin(sensorPair->second, max, min);
+        getSensorMaxMin(sensorMap, max, min);
 
         int16_t mValue = 0;
         int16_t bValue = 0;