blob: f489b7fb7aa703b6ea20b39beee04f1eb2603592 [file] [log] [blame]
Shawn McCarneybfe2c252020-03-10 14:05:19 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "action.hpp"
Bob King462e5922020-11-19 17:48:30 +080017#include "chassis.hpp"
18#include "compare_presence_action.hpp"
19#include "device.hpp"
20#include "i2c_interface.hpp"
Shawn McCarneybfe2c252020-03-10 14:05:19 -050021#include "mock_action.hpp"
Bob King462e5922020-11-19 17:48:30 +080022#include "mock_journal.hpp"
23#include "mock_presence_service.hpp"
24#include "mock_services.hpp"
25#include "mocked_i2c_interface.hpp"
Shawn McCarneybfe2c252020-03-10 14:05:19 -050026#include "presence_detection.hpp"
Bob King462e5922020-11-19 17:48:30 +080027#include "rule.hpp"
28#include "system.hpp"
Shawn McCarneybfe2c252020-03-10 14:05:19 -050029
30#include <memory>
Bob King462e5922020-11-19 17:48:30 +080031#include <stdexcept>
32#include <string>
33#include <tuple>
Shawn McCarneybfe2c252020-03-10 14:05:19 -050034#include <utility>
35#include <vector>
36
Bob King462e5922020-11-19 17:48:30 +080037#include <gmock/gmock.h>
Shawn McCarneybfe2c252020-03-10 14:05:19 -050038#include <gtest/gtest.h>
39
40using namespace phosphor::power::regulators;
41
Bob King462e5922020-11-19 17:48:30 +080042using ::testing::Return;
43using ::testing::Throw;
44
45/**
46 * Creates the parent objects that normally contain a PresenceDetection object.
47 *
48 * A PresenceDetection object is normally contained within a hierarchy of
49 * System, Chassis, and Device objects. These objects are required in order to
50 * call the execute() method.
51 *
52 * Creates the System, Chassis, and Device objects. The PresenceDetection
53 * object is moved into the Device object.
54 *
55 * @param detection PresenceDetection object to move into object hierarchy
56 * @return Pointers to the System, Chassis, and Device objects. The Chassis and
57 * Device objects are contained within the System object and will be
58 * automatically destructed.
59 */
60std::tuple<std::unique_ptr<System>, Chassis*, Device*>
61 createParentObjects(std::unique_ptr<PresenceDetection> detection)
62{
63 // Create mock I2CInterface
64 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
65 std::make_unique<i2c::MockedI2CInterface>();
66
67 // Create Device that contains PresenceDetection
68 std::unique_ptr<Device> device = std::make_unique<Device>(
69 "vdd_reg", true,
70 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
71 std::move(i2cInterface), std::move(detection));
72 Device* devicePtr = device.get();
73
74 // Create Chassis that contains Device
75 std::vector<std::unique_ptr<Device>> devices{};
76 devices.emplace_back(std::move(device));
77 std::unique_ptr<Chassis> chassis =
78 std::make_unique<Chassis>(1, std::move(devices));
79 Chassis* chassisPtr = chassis.get();
80
81 // Create System that contains Chassis
82 std::vector<std::unique_ptr<Rule>> rules{};
83 std::vector<std::unique_ptr<Chassis>> chassisVec{};
84 chassisVec.emplace_back(std::move(chassis));
85 std::unique_ptr<System> system =
86 std::make_unique<System>(std::move(rules), std::move(chassisVec));
87
88 return std::make_tuple(std::move(system), chassisPtr, devicePtr);
89}
90
Shawn McCarneybfe2c252020-03-10 14:05:19 -050091TEST(PresenceDetectionTests, Constructor)
92{
93 std::vector<std::unique_ptr<Action>> actions{};
Bob King462e5922020-11-19 17:48:30 +080094 actions.emplace_back(std::make_unique<MockAction>());
Shawn McCarneybfe2c252020-03-10 14:05:19 -050095
Bob King462e5922020-11-19 17:48:30 +080096 PresenceDetection detection{std::move(actions)};
97 EXPECT_EQ(detection.getActions().size(), 1);
98 EXPECT_FALSE(detection.getCachedPresence().has_value());
99}
100
101TEST(PresenceDetectionTests, ClearCache)
102{
103 // Create MockAction that will return true once
104 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
105 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
106
107 // Create PresenceDetection
108 std::vector<std::unique_ptr<Action>> actions{};
109 actions.emplace_back(std::move(action));
110 PresenceDetection* detection = new PresenceDetection(std::move(actions));
111
112 // Create parent System, Chassis, and Device objects
113 auto [system, chassis, device] =
114 createParentObjects(std::unique_ptr<PresenceDetection>{detection});
115
116 // Verify that initially no presence value is cached
117 EXPECT_FALSE(detection->getCachedPresence().has_value());
118
119 // Call execute() which should obtain and cache presence value
120 MockServices services{};
121 EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));
122
123 // Verify true presence value was cached
124 EXPECT_TRUE(detection->getCachedPresence().has_value());
125 EXPECT_TRUE(detection->getCachedPresence().value());
126
127 // Clear cached presence value
128 detection->clearCache();
129
130 // Verify that no presence value is cached
131 EXPECT_FALSE(detection->getCachedPresence().has_value());
Shawn McCarneybfe2c252020-03-10 14:05:19 -0500132}
133
134TEST(PresenceDetectionTests, Execute)
135{
Bob King462e5922020-11-19 17:48:30 +0800136 // Create ComparePresenceAction
137 std::unique_ptr<ComparePresenceAction> action =
138 std::make_unique<ComparePresenceAction>(
139 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2",
140 true);
141
142 // Create PresenceDetection
143 std::vector<std::unique_ptr<Action>> actions{};
144 actions.emplace_back(std::move(action));
145 PresenceDetection* detection = new PresenceDetection(std::move(actions));
146
147 // Create parent System, Chassis, and Device objects
148 auto [system, chassis, device] =
149 createParentObjects(std::unique_ptr<PresenceDetection>{detection});
150
151 // Test where works: Present: Value is not cached
152 {
153 EXPECT_FALSE(detection->getCachedPresence().has_value());
154
155 // Create MockServices. MockPresenceService::isPresent() should return
156 // true.
157 MockServices services{};
158 MockPresenceService& presenceService =
159 services.getMockPresenceService();
160 EXPECT_CALL(presenceService,
161 isPresent("/xyz/openbmc_project/inventory/system/chassis/"
162 "motherboard/cpu2"))
163 .Times(1)
164 .WillOnce(Return(true));
165
166 // Execute PresenceDetection
167 EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));
168
169 EXPECT_TRUE(detection->getCachedPresence().has_value());
170 EXPECT_TRUE(detection->getCachedPresence().value());
171 }
172
173 // Test where works: Present: Value is cached
174 {
175 EXPECT_TRUE(detection->getCachedPresence().has_value());
176
177 // Create MockServices. MockPresenceService::isPresent() should not be
178 // called.
179 MockServices services{};
180 MockPresenceService& presenceService =
181 services.getMockPresenceService();
182 EXPECT_CALL(presenceService, isPresent).Times(0);
183
184 // Execute PresenceDetection
185 EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));
186 }
187
188 // Test where works: Not present: Value is not cached
189 {
190 // Clear cached presence value
191 detection->clearCache();
192 EXPECT_FALSE(detection->getCachedPresence().has_value());
193
194 // Create MockServices. MockPresenceService::isPresent() should return
195 // false.
196 MockServices services{};
197 MockPresenceService& presenceService =
198 services.getMockPresenceService();
199 EXPECT_CALL(presenceService,
200 isPresent("/xyz/openbmc_project/inventory/system/chassis/"
201 "motherboard/cpu2"))
202 .Times(1)
203 .WillOnce(Return(false));
204
205 // Execute PresenceDetection
206 EXPECT_FALSE(detection->execute(services, *system, *chassis, *device));
207
208 EXPECT_TRUE(detection->getCachedPresence().has_value());
209 EXPECT_FALSE(detection->getCachedPresence().value());
210 }
211
212 // Test where works: Not present: Value is cached
213 {
214 EXPECT_TRUE(detection->getCachedPresence().has_value());
215
216 // Create MockServices. MockPresenceService::isPresent() should not be
217 // called.
218 MockServices services{};
219 MockPresenceService& presenceService =
220 services.getMockPresenceService();
221 EXPECT_CALL(presenceService, isPresent).Times(0);
222
223 // Execute PresenceDetection
224 EXPECT_FALSE(detection->execute(services, *system, *chassis, *device));
225 }
226
227 // Test where fails
228 {
229 // Clear cached presence value
230 detection->clearCache();
231 EXPECT_FALSE(detection->getCachedPresence().has_value());
232
233 // Create MockServices. MockPresenceService::isPresent() should throw
234 // an exception.
235 MockServices services{};
236 MockPresenceService& presenceService =
237 services.getMockPresenceService();
238 EXPECT_CALL(presenceService,
239 isPresent("/xyz/openbmc_project/inventory/system/chassis/"
240 "motherboard/cpu2"))
241 .Times(1)
242 .WillOnce(
243 Throw(std::runtime_error{"DBusError: Invalid object path."}));
244
245 // Define expected journal messages that should be passed to MockJournal
246 MockJournal& journal = services.getMockJournal();
247 std::vector<std::string> exceptionMessages{
248 "DBusError: Invalid object path.",
249 "ActionError: compare_presence: { fru: "
250 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2, "
251 "value: true }"};
252 EXPECT_CALL(journal, logError(exceptionMessages)).Times(1);
253 EXPECT_CALL(journal,
254 logError("Unable to determine presence of vdd_reg"))
255 .Times(1);
256
257 // Execute PresenceDetection. Should return true when an error occurs.
258 EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));
259
260 EXPECT_TRUE(detection->getCachedPresence().has_value());
261 EXPECT_TRUE(detection->getCachedPresence().value());
262 }
Shawn McCarneybfe2c252020-03-10 14:05:19 -0500263}
264
265TEST(PresenceDetectionTests, GetActions)
266{
267 std::vector<std::unique_ptr<Action>> actions{};
268
269 MockAction* action1 = new MockAction{};
Bob King462e5922020-11-19 17:48:30 +0800270 actions.emplace_back(std::unique_ptr<MockAction>{action1});
Shawn McCarneybfe2c252020-03-10 14:05:19 -0500271
272 MockAction* action2 = new MockAction{};
Bob King462e5922020-11-19 17:48:30 +0800273 actions.emplace_back(std::unique_ptr<MockAction>{action2});
Shawn McCarneybfe2c252020-03-10 14:05:19 -0500274
Bob King462e5922020-11-19 17:48:30 +0800275 PresenceDetection detection{std::move(actions)};
276 EXPECT_EQ(detection.getActions().size(), 2);
277 EXPECT_EQ(detection.getActions()[0].get(), action1);
278 EXPECT_EQ(detection.getActions()[1].get(), action2);
279}
280
281TEST(PresenceDetectionTests, GetCachedPresence)
282{
283 // Create MockAction that will return false once
284 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
285 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
286
287 // Create PresenceDetection
288 std::vector<std::unique_ptr<Action>> actions{};
289 actions.emplace_back(std::move(action));
290 PresenceDetection* detection = new PresenceDetection(std::move(actions));
291
292 // Create parent System, Chassis, and Device objects
293 auto [system, chassis, device] =
294 createParentObjects(std::unique_ptr<PresenceDetection>{detection});
295
296 // Verify that initially no presence value is cached
297 EXPECT_FALSE(detection->getCachedPresence().has_value());
298
299 // Call execute() which should obtain and cache presence value
300 MockServices services{};
301 EXPECT_FALSE(detection->execute(services, *system, *chassis, *device));
302
303 // Verify false presence value was cached
304 EXPECT_TRUE(detection->getCachedPresence().has_value());
305 EXPECT_FALSE(detection->getCachedPresence().value());
306
307 // Clear cached presence value
308 detection->clearCache();
309
310 // Verify that no presence value is cached
311 EXPECT_FALSE(detection->getCachedPresence().has_value());
Shawn McCarneybfe2c252020-03-10 14:05:19 -0500312}