Add --strict-failsafe-pwm compile flag

This build flag is used to set the fans strictly at the failsafe
percent when in failsafe mode, even when the calculated PWM is higher
than failsafe PWM. Without this enabled, the PWM is calculated and set
to the calculated PWM  the failsafe PWM, whichever is higher.

Added a unit test that can test this new build flag code path if the
compile flag is defined.

Tested:

Verified on an internal machine that by adding the following to the
bbappend:

EXTRA_OECONF:append = " --enable-strict-failsafe-pwm=yes"

With flag:
ipmitool sensor list
fan_pwm         | 89.768

Without flag:
ipmitool sensor list
fan_pwm         | 99.960

We can see that the fan pwm was limited to the failsafe percentage when
in failsafe mode with the flag. Without the flag, it ran at 100%

Bug-Id: openbmc/phosphor-pid-control#17
Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: I72a1e5aab8d3e5b0e3716f0b3720d704a6f05008
diff --git a/test/pid_fancontroller_unittest.cpp b/test/pid_fancontroller_unittest.cpp
index 883ca84..f330202 100644
--- a/test/pid_fancontroller_unittest.cpp
+++ b/test/pid_fancontroller_unittest.cpp
@@ -150,7 +150,7 @@
 {
     // Verify that if failsafe mode is enabled and the input value for the fans
     // is below the failsafe minimum value, the input is not used and the fans
-    // are driven at failsafe RPM.
+    // are driven at failsafe RPM (this assumes STRICT_FAILSAFE_PWM is not set)
 
     ZoneMock z;
 
@@ -162,7 +162,7 @@
     EXPECT_FALSE(p == nullptr);
 
     EXPECT_CALL(z, getFailSafeMode()).WillOnce(Return(true));
-    EXPECT_CALL(z, getFailSafePercent()).Times(2).WillRepeatedly(Return(75.0));
+    EXPECT_CALL(z, getFailSafePercent()).WillOnce(Return(75.0));
 
     int64_t timeout = 0;
     std::unique_ptr<Sensor> s1 = std::make_unique<SensorMock>("fan0", timeout);
@@ -223,35 +223,44 @@
     p->outputProc(50.0);
 }
 
-TEST(FanControllerTest, OutputProc_VerifyFailSafeIgnoredIfInputHigher)
+TEST(FanControllerTest, OutputProc_VerifyFailSafeWhenInputHigher)
 {
-    // If the requested output is higher than the failsafe value, then use the
-    // value provided to outputProc.
+    // If STRICT_FAILSAFE_PWM flag is NOT defined and the requested output is
+    // higher than the failsafe value, then use the value provided to outputProc
+    //
+    // If STRICT_FAILSAFE_PWM is defined, we expect the FailSafe PWM to be
+    // capped to the failsafe PWM, and not go higher than that.
 
     ZoneMock z;
 
     std::vector<std::string> inputs = {"fan0"};
     ec::pidinfo initial;
+    const double failsafePWM = 75.0;
 
     std::unique_ptr<PIDController> p =
         FanController::createFanPid(&z, "fan1", inputs, initial);
     EXPECT_FALSE(p == nullptr);
 
     EXPECT_CALL(z, getFailSafeMode()).WillOnce(Return(true));
-    EXPECT_CALL(z, getFailSafePercent()).WillOnce(Return(75.0));
+    EXPECT_CALL(z, getFailSafePercent()).WillOnce(Return(failsafePWM));
 
     int64_t timeout = 0;
     std::unique_ptr<Sensor> s1 = std::make_unique<SensorMock>("fan0", timeout);
     // Grab pointer for mocking.
     SensorMock* sm1 = reinterpret_cast<SensorMock*>(s1.get());
 
-    // Converting from double to double for expectation.
     double percent = 80;
-    double value = percent / 100;
 
     EXPECT_CALL(z, getRedundantWrite()).WillOnce(Return(false));
     EXPECT_CALL(z, getSensor(StrEq("fan0"))).WillOnce(Return(s1.get()));
+#ifdef STRICT_FAILSAFE_PWM
+    double failsafeValue = failsafePWM / 100;
+    EXPECT_CALL(*sm1, write(failsafeValue, false, _));
+#else
+    // Converting from double to double for expectation.
+    double value = percent / 100;
     EXPECT_CALL(*sm1, write(value, false, _));
+#endif
 
     // This is a fan PID, so calling outputProc will try to write this value
     // to the sensors.