Implementing the TempToMargin feature

Wrapping the input name std::string in a new structure SensorInput, so
that the TempToMargin information can be cleanly carried along with
it, all the way down to the PID input processing layer where it is
needed. This allows the conversion to be done just-in-time before the
temperature reading is interpreted, minimizing the blast radius of
this change. Nonetheless, because of the type change, there was a
somewhat large blast radius to implement this feature.

The design, and the documentation, is already here:
https://github.com/openbmc/phosphor-pid-control/issues/23

Tested: Added unit tests for JSON parsing and for proper execution
of the TempToMargin feature. They pass. Ran it locally, on our
appropriately-configured system, and it seems to work for me.

Change-Id: I598ba485195aaa70c26e91a1da3ab88fff8c3a4c
Signed-off-by: Josh Lehan <krellan@google.com>
diff --git a/test/pid_thermalcontroller_unittest.cpp b/test/pid_thermalcontroller_unittest.cpp
index 6069154..7aee1e1 100644
--- a/test/pid_thermalcontroller_unittest.cpp
+++ b/test/pid_thermalcontroller_unittest.cpp
@@ -1,3 +1,4 @@
+#include "conf.hpp"
 #include "pid/ec/logging.hpp"
 #include "pid/ec/pid.hpp"
 #include "pid/thermalcontroller.hpp"
@@ -25,7 +26,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -41,7 +42,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {};
+    std::vector<pid_control::conf::SensorInput> inputs = {};
     double setpoint = 10.0;
     ec::pidinfo initial;
     std::unique_ptr<PIDController> p;
@@ -60,7 +61,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -79,7 +80,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -96,7 +97,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -117,7 +118,8 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0", "fleeting1"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"},
+                                                          {"fleeting1"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -138,7 +140,8 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0", "fleeting1"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"},
+                                                          {"fleeting1"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -159,7 +162,8 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0", "fleeting1"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"},
+                                                          {"fleeting1"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
 
@@ -173,6 +177,29 @@
     EXPECT_EQ(15.0, p->inputProc());
 }
 
+TEST(ThermalControllerTest, InputProc_MultipleInputsTempToMargin)
+{
+    // This test verifies inputProc behaves as expected with multiple margin
+    // inputs and TempToMargin in use.
+
+    ZoneMock z;
+
+    std::vector<pid_control::conf::SensorInput> inputs = {
+        {"absolute0", 85.0, true}, {"margin1"}};
+    double setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p = ThermalController::createThermalPid(
+        &z, "therm1", inputs, setpoint, initial, ThermalType::margin);
+    EXPECT_FALSE(p == nullptr);
+
+    EXPECT_CALL(z, getCachedValue(StrEq("absolute0"))).WillOnce(Return(82.0));
+    EXPECT_CALL(z, getCachedValue(StrEq("margin1"))).WillOnce(Return(5.0));
+
+    // 82 degrees temp, 85 degrees Tjmax => 3 degrees of safety margin
+    EXPECT_EQ(3.0, p->inputProc());
+}
+
 TEST(ThermalControllerTest, NegHysteresis_BehavesAsExpected)
 {
     // This test verifies Negative hysteresis behaves as expected by
@@ -181,7 +208,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
     initial.negativeHysteresis = 4.0;
@@ -214,7 +241,7 @@
 
     ZoneMock z;
 
-    std::vector<std::string> inputs = {"fleeting0"};
+    std::vector<pid_control::conf::SensorInput> inputs = {{"fleeting0"}};
     double setpoint = 10.0;
     ec::pidinfo initial;
     initial.positiveHysteresis = 5.0;