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