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