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