test: pid: thermalcontroller

Tests for the pid/thermalcontroller module.
Fixes a bug where one could pass an incorrect number of inputs
to the thermalcontroller.  This can still be side-stepped by calling the
constructor directly.

Tested: Ran on quanta-q71l board and it behaved as expected.

Change-Id: I3153ae4d907d9f90787b03e9d013d4349d911948
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index ec40421..6bd5138 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -12,7 +12,8 @@
 
 # Run all 'check' test programs
 check_PROGRAMS = sensor_manager_unittest sensor_pluggable_unittest \
- sensor_host_unittest util_unittest pid_zone_unittest
+ sensor_host_unittest util_unittest pid_zone_unittest \
+ pid_thermalcontroller_unittest
 TESTS = $(check_PROGRAMS)
 
 # Until libconfig is mocked out or replaced, include it.
@@ -32,3 +33,8 @@
 pid_zone_unittest_LDADD = $(top_builddir)/pid/ec/pid.o \
  $(top_builddir)/sensors/manager.o $(top_builddir)/pid/controller.o \
  $(top_builddir)/pid/zone.o
+
+pid_thermalcontroller_unittest_SOURCES = pid_thermalcontroller_unittest.cpp
+pid_thermalcontroller_unittest_LDADD = $(top_builddir)/pid/ec/pid.o \
+ $(top_builddir)/pid/util.o $(top_builddir)/pid/controller.o \
+ $(top_builddir)/pid/thermalcontroller.o
diff --git a/test/pid_thermalcontroller_unittest.cpp b/test/pid_thermalcontroller_unittest.cpp
new file mode 100644
index 0000000..b0de1a9
--- /dev/null
+++ b/test/pid_thermalcontroller_unittest.cpp
@@ -0,0 +1,116 @@
+#include "pid/thermalcontroller.hpp"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <string>
+#include <vector>
+
+#include "pid/ec/pid.hpp"
+#include "test/zone_mock.hpp"
+
+using ::testing::Return;
+using ::testing::StrEq;
+
+TEST(ThermalControllerTest, BoringFactoryTest) {
+    // Verifies building a ThermalPIDController with the factory works as
+    // expected in the boring (uninteresting) case.
+
+    ZoneMock z;
+
+    std::vector<std::string> inputs = {"fleeting0"};
+    float setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p =
+        ThermalController::CreateThermalPid(&z, "therm1", inputs, setpoint,
+                                            initial);
+    // Success
+    EXPECT_FALSE(p == nullptr);
+}
+
+TEST(ThermalControllerTest, VerifyFactoryFailsWithZeroInputs) {
+    // A thermal controller needs at least one input.
+
+    ZoneMock z;
+
+    std::vector<std::string> inputs = {};
+    float setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p =
+        ThermalController::CreateThermalPid(&z, "therm1", inputs, setpoint,
+                                            initial);
+    EXPECT_TRUE(p == nullptr);
+}
+
+TEST(ThermalControllerTest, VerifyFactoryFailsForMoreThanOneInput) {
+    // ThermalControllers currently only support one input, so don't let
+    // someone accidentally specify more.
+
+    ZoneMock z;
+
+    std::vector<std::string> inputs = {"fleeting0", "asdf"};
+    float setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p =
+        ThermalController::CreateThermalPid(&z, "therm1", inputs, setpoint,
+                                            initial);
+    EXPECT_TRUE(p == nullptr);
+}
+
+TEST(ThermalControllerTest, InputProc_BehavesAsExpected) {
+    // This test just verifies input_proc behaves as expected.
+
+    ZoneMock z;
+
+    std::vector<std::string> inputs = {"fleeting0"};
+    float setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p =
+        ThermalController::CreateThermalPid(&z, "therm1", inputs, setpoint,
+                                            initial);
+    EXPECT_FALSE(p == nullptr);
+
+    EXPECT_CALL(z, getCachedValue(StrEq("fleeting0"))).WillOnce(Return(5.0));
+
+    EXPECT_EQ(5.0, p->input_proc());
+}
+
+TEST(ThermalControllerTest, SetPtProc_BehavesAsExpected) {
+    // This test just verifies input_proc behaves as expected.
+
+    ZoneMock z;
+
+    std::vector<std::string> inputs = {"fleeting0"};
+    float setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p =
+        ThermalController::CreateThermalPid(&z, "therm1", inputs, setpoint,
+                                            initial);
+    EXPECT_FALSE(p == nullptr);
+
+    EXPECT_EQ(setpoint, p->setpt_proc());
+}
+
+TEST(ThermalControllerTest, OutputProc_BehavesAsExpected) {
+    // This test just verifies input_proc behaves as expected.
+
+    ZoneMock z;
+
+    std::vector<std::string> inputs = {"fleeting0"};
+    float setpoint = 10.0;
+    ec::pidinfo initial;
+
+    std::unique_ptr<PIDController> p =
+        ThermalController::CreateThermalPid(&z, "therm1", inputs, setpoint,
+                                            initial);
+    EXPECT_FALSE(p == nullptr);
+
+    float value = 90.0;
+    EXPECT_CALL(z, addRPMSetPoint(value));
+
+    p->output_proc(value);
+}