xref: /openbmc/phosphor-pid-control/test/sensor_host_unittest.cpp (revision f8b6e55147148c3cfb42327ff267197a460b411c)
1 #include "interfaces.hpp"
2 #include "sensors/host.hpp"
3 #include "sensors/sensor.hpp"
4 #include "test/helpers.hpp"
5 
6 #include <systemd/sd-bus.h>
7 
8 #include <sdbusplus/test/sdbus_mock.hpp>
9 
10 #include <chrono>
11 #include <cstdint>
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
16 #include <gmock/gmock.h>
17 #include <gtest/gtest.h>
18 
19 namespace pid_control
20 {
21 namespace
22 {
23 
24 using ::testing::IsNull;
25 using ::testing::Return;
26 using ::testing::StrEq;
27 
28 TEST(HostSensorTest, BoringConstructorTest)
29 {
30     // WARN: The host sensor is not presently meant to be created this way,
31     // TODO: Can I move the constructor into private?
32 }
33 
34 TEST(HostSensorTest, CreateHostTempSensorTest)
35 {
36     // The normal case for this sensor is to be a temperature sensor, where
37     // the value is treated as a margin sensor.
38 
39     sdbusplus::SdBusMock sdbus_mock;
40     auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
41     std::string name = "fleeting0";
42     int64_t timeout = 1;
43     const char* objPath = "/asdf/asdf0";
44     bool defer = false;
45     std::string interface = "xyz.openbmc_project.Sensor.Value";
46 
47     std::vector<std::string> properties = {};
48     double d;
49 
50     // The createTemp updates all the properties, however, only Scale is set
51     // to non-default.
52     SetupDbusObject(&sdbus_mock, defer, objPath, interface, properties, &d);
53 
54     // This is called during object destruction.
55     EXPECT_CALL(sdbus_mock,
56                 sd_bus_emit_object_removed(IsNull(), StrEq(objPath)))
57         .WillOnce(Return(0));
58 
59     std::unique_ptr<Sensor> s =
60         HostSensor::createTemp(name, timeout, bus_mock, objPath, defer);
61 }
62 
63 TEST(HostSensorTest, VerifyWriteThenReadMatches)
64 {
65     // Verify that when value is updated, the information matches
66     // what we expect when read back.
67 
68     sdbusplus::SdBusMock sdbus_mock;
69     auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
70     std::string name = "fleeting0";
71     int64_t timeout = 1;
72     const char* objPath = "/asdf/asdf0";
73     bool defer = false;
74     std::string interface = "xyz.openbmc_project.Sensor.Value";
75 
76     std::vector<std::string> properties = {};
77     double d;
78 
79     SetupDbusObject(&sdbus_mock, defer, objPath, interface, properties, &d);
80 
81     EXPECT_CALL(sdbus_mock,
82                 sd_bus_emit_object_removed(IsNull(), StrEq(objPath)))
83         .WillOnce(Return(0));
84 
85     std::unique_ptr<Sensor> s =
86         HostSensor::createTemp(name, timeout, bus_mock, objPath, defer);
87 
88     // Value is updated from dbus calls only (normally).
89     HostSensor* hs = static_cast<HostSensor*>(s.get());
90     double new_value = 2;
91 
92     ReadReturn r = hs->read();
93     EXPECT_EQ(r.value, 0);
94 
95     EXPECT_CALL(sdbus_mock,
96                 sd_bus_emit_properties_changed_strv(
97                     IsNull(), StrEq(objPath), StrEq(interface), NotNull()))
98         .WillOnce(Invoke(
99             [=]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path,
100                 [[maybe_unused]] const char* interface, const char** names) {
101                 EXPECT_STREQ("Value", names[0]);
102                 return 0;
103             }));
104 
105     std::chrono::high_resolution_clock::time_point t1 =
106         std::chrono::high_resolution_clock::now();
107 
108     hs->value(new_value);
109     r = hs->read();
110     EXPECT_EQ(r.value, new_value);
111 
112     auto duration =
113         std::chrono::duration_cast<std::chrono::seconds>(t1 - r.updated)
114             .count();
115 
116     // Verify it was updated within the last second.
117     EXPECT_TRUE(duration < 1);
118 }
119 
120 } // namespace
121 } // namespace pid_control
122