blob: e84de8971b7ebb345b87d5543172fe5fa42b88bd [file] [log] [blame]
Patrick Venture0ef1faf2018-06-13 12:50:53 -07001#include "dbus/dbuspassive.hpp"
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5#include <sdbusplus/test/sdbus_mock.hpp>
6#include <string>
7
8#include "test/dbushelper_mock.hpp"
9
10using ::testing::InSequence;
11using ::testing::Invoke;
12using ::testing::IsNull;
13using ::testing::NotNull;
14using ::testing::Return;
15using ::testing::StrEq;
16using ::testing::_;
17
18std::string SensorIntf = "xyz.openbmc_project.Sensor.Value";
19
20TEST(DbusPassiveTest, FactoryFailsWithInvalidType) {
21 // Verify the type is checked by the factory.
22
23 sdbusplus::SdBusMock sdbus_mock;
24 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
25 std::string type = "invalid";
26 std::string id = "id";
27
28 DbusHelperMock helper;
29
30 std::unique_ptr<ReadInterface> ri =
31 DbusPassive::CreateDbusPassive(bus_mock, type, id, &helper);
32
33 EXPECT_EQ(ri, nullptr);
34}
35
36TEST(DbusPassiveTest, BoringConstructorTest) {
37 // Just build the object, which should be avoided as this does no error
38 // checking at present.
39
40 sdbusplus::SdBusMock sdbus_mock;
41 auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
42 std::string type = "invalid";
43 std::string id = "id";
44 std::string path = "/xyz/openbmc_project/sensors/unknown/id";
45
46 DbusHelperMock helper;
47 EXPECT_CALL(helper, GetService(_, StrEq(SensorIntf), StrEq(path)))
48 .WillOnce(Return("asdf"));
49
50 EXPECT_CALL(helper, GetProperties(_, StrEq("asdf"), StrEq(path),
51 NotNull()))
52 .WillOnce(Invoke([&](sdbusplus::bus::bus& bus,
53 const std::string& service,
54 const std::string& path,
55 struct SensorProperties* prop) {
56 prop->scale = -3;
57 prop->value = 10;
58 prop->unit = "x";
59 }));
60
61 DbusPassive(bus_mock, type, id, &helper);
62 // Success
63}
64
65class DbusPassiveTestObj : public ::testing::Test {
66 protected:
67 DbusPassiveTestObj()
68 : sdbus_mock(),
69 bus_mock(std::move(sdbusplus::get_mocked_new(&sdbus_mock))),
70 helper()
71 {
72 EXPECT_CALL(helper, GetService(_, StrEq(SensorIntf), StrEq(path)))
73 .WillOnce(Return("asdf"));
74
75 EXPECT_CALL(helper, GetProperties(_, StrEq("asdf"), StrEq(path),
76 NotNull()))
77 .WillOnce(Invoke([&](sdbusplus::bus::bus& bus,
78 const std::string& service,
79 const std::string& path,
80 struct SensorProperties* prop) {
81 prop->scale = _scale;
82 prop->value = _value;
83 prop->unit = "x";
84 }));
85
86 ri = DbusPassive::CreateDbusPassive(bus_mock, type, id, &helper);
87 passive = reinterpret_cast<DbusPassive*>(ri.get());
88 EXPECT_FALSE(passive == nullptr);
89 }
90
91 sdbusplus::SdBusMock sdbus_mock;
92 sdbusplus::bus::bus bus_mock;
93 DbusHelperMock helper;
94 std::string type = "temp";
95 std::string id = "id";
96 std::string path = "/xyz/openbmc_project/sensors/temperature/id";
97 int64_t _scale = -3;
98 int64_t _value = 10;
99
100 std::unique_ptr<ReadInterface> ri;
101 DbusPassive *passive;
102};
103
104TEST_F(DbusPassiveTestObj, ReadReturnsExpectedValues) {
105 // Verify read is returning the values.
106 ReadReturn v;
107 v.value = 0.01;
108 // TODO: updated is set when the value is created, so we can range check
109 // it.
110 ReadReturn r = passive->read();
111 EXPECT_EQ(v.value, r.value);
112}
113
114TEST_F(DbusPassiveTestObj, SetValueUpdatesValue) {
115 // Verify setvalue does as advertised.
116
117 double value = 0.01;
118 passive->setValue(value);
119
120 // TODO: updated is set when the value is set, so we can range check it.
121 ReadReturn r = passive->read();
122 EXPECT_EQ(value, r.value);
123}
124
125TEST_F(DbusPassiveTestObj, GetScaleReturnsExpectedValue) {
126 // Verify the scale is returned as expected.
127 EXPECT_EQ(_scale, passive->getScale());
128}
129
130TEST_F(DbusPassiveTestObj, GetIdReturnsExpectedValue) {
131 // Verify getId returns the expected value.
132 EXPECT_EQ(id, passive->getId());
133}
134
135TEST_F(DbusPassiveTestObj, VerifyHandlesDbusSignal) {
136 // The dbus passive sensor listens for updates and if it's the Value
137 // property, it needs to handle it.
138
139 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
140 .WillOnce(Return(nullptr));
141 sdbusplus::message::message msg(nullptr, &sdbus_mock);
142
143 const char *Value = "Value";
144 int64_t xValue = 10000;
145 const char *intf = "xyz.openbmc_project.Sensor.Value";
146 // string, std::map<std::string, sdbusplus::message::variant<int64_t>>
147 // msg.read(msgSensor, msgData);
148
149 EXPECT_CALL(sdbus_mock,
150 sd_bus_message_read_basic(IsNull(), 's', NotNull()))
151 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) {
152 const char **s = static_cast<const char **>(p);
153 // Read the first parameter, the string.
154 *s = intf;
155 return 0;
156 }))
157 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) {
158 const char **s = static_cast<const char **>(p);
159 *s = Value;
160 // Read the string in the pair (dictionary).
161 return 0;
162 }));
163
164 // std::map
165 EXPECT_CALL(sdbus_mock,
166 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
167 .WillOnce(Return(0));
168
169 // while !at_end()
170 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
171 .WillOnce(Return(0))
172 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
173
174 // std::pair
175 EXPECT_CALL(sdbus_mock,
176 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
177 .WillOnce(Return(0));
178
179 EXPECT_CALL(sdbus_mock,
180 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
181 .WillOnce(Return(1));
182 EXPECT_CALL(sdbus_mock,
183 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
184 .WillOnce(Return(0));
185
186 EXPECT_CALL(sdbus_mock,
187 sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
188 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) {
189 int64_t *s = static_cast<int64_t *>(p);
190 *s = xValue;
191 return 0;
192 }));
193
194 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
195 .WillOnce(Return(0)) /* variant. */
196 .WillOnce(Return(0)) /* std::pair */
197 .WillOnce(Return(0)); /* std::map */
198
199 int rv = HandleSensorValue(msg, passive);
200 EXPECT_EQ(rv, 0); // It's always 0.
201
202 ReadReturn r = passive->read();
203 EXPECT_EQ(10, r.value);
204}
205
206TEST_F(DbusPassiveTestObj, VerifyIgnoresOtherPropertySignal) {
207 // The dbus passive sensor listens for updates and if it's the Value
208 // property, it needs to handle it. In this case, it won't be.
209
210 EXPECT_CALL(sdbus_mock, sd_bus_message_ref(IsNull()))
211 .WillOnce(Return(nullptr));
212 sdbusplus::message::message msg(nullptr, &sdbus_mock);
213
214 const char *Scale = "Scale";
215 int64_t xScale = -6;
216 const char *intf = "xyz.openbmc_project.Sensor.Value";
217 // string, std::map<std::string, sdbusplus::message::variant<int64_t>>
218 // msg.read(msgSensor, msgData);
219
220 EXPECT_CALL(sdbus_mock,
221 sd_bus_message_read_basic(IsNull(), 's', NotNull()))
222 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) {
223 const char **s = static_cast<const char **>(p);
224 // Read the first parameter, the string.
225 *s = intf;
226 return 0;
227 }))
228 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) {
229 const char **s = static_cast<const char **>(p);
230 *s = Scale;
231 // Read the string in the pair (dictionary).
232 return 0;
233 }));
234
235 // std::map
236 EXPECT_CALL(sdbus_mock,
237 sd_bus_message_enter_container(IsNull(), 'a', StrEq("{sv}")))
238 .WillOnce(Return(0));
239
240 // while !at_end()
241 EXPECT_CALL(sdbus_mock, sd_bus_message_at_end(IsNull(), 0))
242 .WillOnce(Return(0))
243 .WillOnce(Return(1)); // So it exits the loop after reading one pair.
244
245 // std::pair
246 EXPECT_CALL(sdbus_mock,
247 sd_bus_message_enter_container(IsNull(), 'e', StrEq("sv")))
248 .WillOnce(Return(0));
249
250 EXPECT_CALL(sdbus_mock,
251 sd_bus_message_verify_type(IsNull(), 'v', StrEq("x")))
252 .WillOnce(Return(1));
253 EXPECT_CALL(sdbus_mock,
254 sd_bus_message_enter_container(IsNull(), 'v', StrEq("x")))
255 .WillOnce(Return(0));
256
257 EXPECT_CALL(sdbus_mock,
258 sd_bus_message_read_basic(IsNull(), 'x', NotNull()))
259 .WillOnce(Invoke([&](sd_bus_message *m, char type, void *p) {
260 int64_t *s = static_cast<int64_t *>(p);
261 *s = xScale;
262 return 0;
263 }));
264
265 EXPECT_CALL(sdbus_mock, sd_bus_message_exit_container(IsNull()))
266 .WillOnce(Return(0)) /* variant. */
267 .WillOnce(Return(0)) /* std::pair */
268 .WillOnce(Return(0)); /* std::map */
269
270 int rv = HandleSensorValue(msg, passive);
271 EXPECT_EQ(rv, 0); // It's always 0.
272
273 ReadReturn r = passive->read();
274 EXPECT_EQ(0.01, r.value);
275}