1 #include "ledlayout.hpp"
2 #include "manager.hpp"
3 
4 #include <sdbusplus/bus.hpp>
5 #include <xyz/openbmc_project/Led/Physical/server.hpp>
6 
7 #include <set>
8 
9 #include <gtest/gtest.h>
10 
11 using namespace phosphor::led;
12 class LedTest : public ::testing::Test
13 {
14   public:
15     sdbusplus::bus_t bus;
16     LedTest() : bus(sdbusplus::bus::new_default())
17     {
18         // Nothing here
19     }
20     ~LedTest()
21     {
22         // Leaving up to auto cleanup.
23     }
24 };
25 
26 static void assertMap(std::map<LedName, Layout::LedAction> map,
27                       std::map<LedName, Layout::Action> expect)
28 {
29     EXPECT_EQ(map.size(), expect.size());
30     for (auto& [key, expect_value] : expect)
31     {
32         ASSERT_TRUE(map.contains(key));
33         EXPECT_EQ(expect_value, map[key].action);
34     }
35 }
36 
37 static const phosphor::led::GroupMap groups1 = {
38     {"/xyz/openbmc_project/ledmanager/groups/groupA",
39      {0,
40       {
41           {"led1", Layout::Action::On, 0, 0, std::nullopt},
42           {"led2", Layout::Action::On, 0, 0, std::nullopt},
43       }}},
44     {"/xyz/openbmc_project/ledmanager/groups/groupB",
45      {0,
46       {
47           {"led3", Layout::Action::On, 0, 0, std::nullopt},
48           {"led4", Layout::Action::On, 0, 0, std::nullopt},
49       }}},
50 };
51 
52 /** @brief Assert one group*/
53 TEST_F(LedTest, assertOneGroup)
54 {
55     Manager manager(bus, groups1);
56 
57     std::set<const Layout::GroupLayout*> assertedGroups;
58 
59     Layout::GroupLayout mygroup =
60         groups1.at("/xyz/openbmc_project/ledmanager/groups/groupA");
61 
62     assertedGroups.insert(&mygroup);
63 
64     std::map<LedName, Layout::LedAction> map =
65         manager.getNewMap(assertedGroups);
66 
67     assertMap(map, {
68                        {"led1", Layout::Action::On},
69                        {"led2", Layout::Action::On},
70                    });
71 }
72 
73 static const phosphor::led::GroupMap groups2 = {
74     {"/xyz/openbmc_project/ledmanager/groups/groupA",
75      {0,
76       {
77           {"led1", Layout::Action::On, 0, 0, std::nullopt},
78           {"led2", Layout::Action::On, 0, 0, std::nullopt},
79       }}},
80     {"/xyz/openbmc_project/ledmanager/groups/groupB",
81      {2,
82       {
83           {"led2", Layout::Action::Off, 0, 0, std::nullopt},
84           {"led3", Layout::Action::On, 0, 0, std::nullopt},
85       }}},
86     {"/xyz/openbmc_project/ledmanager/groups/groupC",
87      {1,
88       {
89           {"led3", Layout::Action::Blink, 0, 0, std::nullopt},
90           {"led4", Layout::Action::Blink, 0, 0, std::nullopt},
91       }}},
92 };
93 
94 /** @brief Assert multiple groups which overwrite each other*/
95 TEST_F(LedTest, assertMultipleGroups)
96 {
97     Manager manager(bus, groups2);
98 
99     std::set<const Layout::GroupLayout*> assertedGroups;
100 
101     Layout::GroupLayout groupA =
102         groups2.at("/xyz/openbmc_project/ledmanager/groups/groupA");
103     Layout::GroupLayout groupB =
104         groups2.at("/xyz/openbmc_project/ledmanager/groups/groupB");
105     Layout::GroupLayout groupC =
106         groups2.at("/xyz/openbmc_project/ledmanager/groups/groupC");
107 
108     assertedGroups.insert(&groupA);
109     assertedGroups.insert(&groupB);
110     assertedGroups.insert(&groupC);
111 
112     std::map<LedName, Layout::LedAction> map =
113         manager.getNewMap(assertedGroups);
114 
115     assertMap(map, {
116                        {"led1", Layout::Action::On},
117                        {"led2", Layout::Action::Off},
118                        {"led3", Layout::Action::On},
119                        {"led4", Layout::Action::Blink},
120                    });
121 }
122 
123 TEST_F(LedTest, test_OCP_Panel_Indicator_6_1_System_Power_Status)
124 {
125     const int dutyon = 50; // Spec says 50% duty cycle
126     const int period = 1;  // Spec says 1Hz
127 
128     // Example from OCP Panel Indicator Specification rev 1.0, Section 6.1
129     // "System Power Control / Status"
130     // The group priorities here are chosen arbitrarily, assuming that locating
131     // the hw has highest priority
132     const std::string groupOffServiceAction =
133         "/xyz/openbmc_project/ledmanager/groups/SysOffServiceAction";
134     const std::string groupSysOnOk =
135         "/xyz/openbmc_project/ledmanager/groups/SysOnOK";
136     const std::string groupSysOffFault =
137         "/xyz/openbmc_project/ledmanager/groups/SysOffFault";
138     const std::string groupSysOnLocate =
139         "/xyz/openbmc_project/ledmanager/groups/SysOnLocate";
140     const std::string groupSysOffLocate =
141         "/xyz/openbmc_project/ledmanager/groups/SysOffLocate";
142     const std::string groupSysOnFault =
143         "/xyz/openbmc_project/ledmanager/groups/SysOnFault";
144 
145     const std::string pwr = "pwr";
146     const std::string fault = "fault";
147 
148     static const phosphor::led::GroupMap groups_ocp_6_1_power_control = {
149         {groupOffServiceAction,
150          {2,
151           {
152               {pwr, Layout::Action::Off, 0, 0, std::nullopt},
153               {fault, Layout::Action::Off, 0, 0, std::nullopt},
154           }}},
155         {groupSysOnOk,
156          {3,
157           {
158               {pwr, Layout::Action::On, 0, 0, std::nullopt},
159               {fault, Layout::Action::Off, 0, 0, std::nullopt},
160           }}},
161         {groupSysOffFault,
162          {38,
163           {
164               {pwr, Layout::Action::Off, 0, 0, std::nullopt},
165               {fault, Layout::Action::On, 0, 0, std::nullopt},
166           }}},
167         {groupSysOnLocate,
168          {99,
169           {
170               {pwr, Layout::Action::On, 0, 0, std::nullopt},
171               {fault, Layout::Action::Blink, dutyon, period, std::nullopt},
172           }}},
173         {groupSysOffLocate,
174          {98,
175           {
176               {pwr, Layout::Action::Off, 0, 0, std::nullopt},
177               {fault, Layout::Action::Blink, dutyon, period, std::nullopt},
178           }}},
179         {groupSysOnFault,
180          {39,
181           {
182               {pwr, Layout::Action::On, 0, 0, std::nullopt},
183               {fault, Layout::Action::On, 0, 0, std::nullopt},
184           }}},
185     };
186 
187     const phosphor::led::GroupMap* groups = &groups_ocp_6_1_power_control;
188 
189     Manager manager(bus, *groups);
190 
191     std::set<const Layout::GroupLayout*> assertedGroups;
192 
193     // Off Service Action
194     assertedGroups.insert(&groups->at(groupOffServiceAction));
195 
196     assertMap(manager.getNewMap(assertedGroups),
197               {
198                   {pwr, Layout::Action::Off},
199                   {fault, Layout::Action::Off},
200               });
201 
202     // On Ok
203     assertedGroups.insert(&groups->at(groupSysOnOk));
204     assertMap(manager.getNewMap(assertedGroups),
205               {
206                   {pwr, Layout::Action::On},
207                   {fault, Layout::Action::Off},
208               });
209 
210     // Off Fault
211     assertedGroups.insert(&groups->at(groupSysOffFault));
212     assertMap(manager.getNewMap(assertedGroups),
213               {
214                   {pwr, Layout::Action::Off},
215                   {fault, Layout::Action::On},
216               });
217 
218     // Off Fault
219     assertedGroups.insert(&groups->at(groupSysOffFault));
220     assertMap(manager.getNewMap(assertedGroups),
221               {
222                   {pwr, Layout::Action::Off},
223                   {fault, Layout::Action::On},
224               });
225 
226     // On Fault
227     assertedGroups.insert(&groups->at(groupSysOnFault));
228     assertMap(manager.getNewMap(assertedGroups),
229               {
230                   {pwr, Layout::Action::On},
231                   {fault, Layout::Action::On},
232               });
233 
234     // Off Locate
235     assertedGroups.insert(&groups->at(groupSysOffLocate));
236     assertMap(manager.getNewMap(assertedGroups),
237               {
238                   {pwr, Layout::Action::Off},
239                   {fault, Layout::Action::Blink},
240               });
241 
242     // On Locate
243     assertedGroups.insert(&groups->at(groupSysOnLocate));
244     assertMap(manager.getNewMap(assertedGroups),
245               {
246                   {pwr, Layout::Action::On},
247                   {fault, Layout::Action::Blink},
248               });
249 }
250 
251 TEST_F(LedTest, test_OCP_Panel_Indicator_6_5_BBU_status)
252 {
253     // Example from OCP Panel Indicator Specification rev 1.0, Section 6.5
254     // "BBU Status"
255     // The group priorities here are chosen arbitrarily, assuming that locating
256     // the hw has highest priority
257     const std::string gBBUSleep =
258         "/xyz/openbmc_project/ledmanager/groups/BBUSleep";
259     const std::string gBBUOn = "/xyz/openbmc_project/ledmanager/groups/BBUOn";
260     const std::string gBBUFault =
261         "/xyz/openbmc_project/ledmanager/groups/BBUFault";
262     const std::string gBBUUnderVolt =
263         "/xyz/openbmc_project/ledmanager/groups/BBUUnderVolt";
264     const std::string gBBUEOL = "/xyz/openbmc_project/ledmanager/groups/BBUEOL";
265     const std::string gBBUOffLocate =
266         "/xyz/openbmc_project/ledmanager/groups/BBUOffLocate";
267     const std::string gBBUOnLocate =
268         "/xyz/openbmc_project/ledmanager/groups/BBUOnLocate";
269 
270     const std::string bbu_ok = "bbu_ok";
271     const std::string bbu_fault = "bbu_fault";
272     const std::string bbu_lowv = "bbu_lowv";
273     const std::string bbu_eol = "bbu_eol";
274 
275     static const phosphor::led::GroupMap groups_ocp_6_5_bbu_status = {
276         {gBBUSleep,
277          {9,
278           {
279               {bbu_ok, Layout::Action::Off, 0, 0, std::nullopt},
280               {bbu_fault, Layout::Action::Off, 0, 0, std::nullopt},
281               {bbu_lowv, Layout::Action::Off, 0, 0, std::nullopt},
282               {bbu_eol, Layout::Action::Off, 0, 0, std::nullopt},
283           }}},
284         {gBBUOn,
285          {10,
286           {
287               {bbu_ok, Layout::Action::On, 0, 0, std::nullopt},
288               {bbu_fault, Layout::Action::Off, 0, 0, std::nullopt},
289               {bbu_lowv, Layout::Action::Off, 0, 0, std::nullopt},
290               {bbu_eol, Layout::Action::Off, 0, 0, std::nullopt},
291           }}},
292         {gBBUFault,
293          {38,
294           {
295               {bbu_ok, Layout::Action::Off, 0, 0, std::nullopt},
296               {bbu_fault, Layout::Action::On, 0, 0, std::nullopt},
297               {bbu_lowv, Layout::Action::Off, 0, 0, std::nullopt},
298               {bbu_eol, Layout::Action::Off, 0, 0, std::nullopt},
299           }}},
300         {gBBUUnderVolt,
301          {39,
302           {
303               {bbu_ok, Layout::Action::Off, 0, 0, std::nullopt},
304               {bbu_fault, Layout::Action::On, 0, 0, std::nullopt},
305               {bbu_lowv, Layout::Action::On, 0, 0, std::nullopt},
306               {bbu_eol, Layout::Action::Off, 0, 0, std::nullopt},
307           }}},
308         {gBBUEOL,
309          {40,
310           {
311               {bbu_ok, Layout::Action::Off, 0, 0, std::nullopt},
312               {bbu_fault, Layout::Action::On, 0, 0, std::nullopt},
313               {bbu_lowv, Layout::Action::Off, 0, 0, std::nullopt},
314               {bbu_eol, Layout::Action::On, 0, 0, std::nullopt},
315           }}},
316         {gBBUOffLocate,
317          {98,
318           {
319               {bbu_ok, Layout::Action::Off, 0, 0, std::nullopt},
320               {bbu_fault, Layout::Action::Blink, 0, 0, std::nullopt},
321               {bbu_lowv, Layout::Action::Off, 0, 0, std::nullopt},
322               {bbu_eol, Layout::Action::Off, 0, 0, std::nullopt},
323           }}},
324         {gBBUOnLocate,
325          {99,
326           {
327               {bbu_ok, Layout::Action::On, 0, 0, std::nullopt},
328               {bbu_fault, Layout::Action::Blink, 0, 0, std::nullopt},
329               {bbu_lowv, Layout::Action::Off, 0, 0, std::nullopt},
330               {bbu_eol, Layout::Action::Off, 0, 0, std::nullopt},
331           }}},
332     };
333 
334     const phosphor::led::GroupMap* groups = &groups_ocp_6_5_bbu_status;
335 
336     Manager manager(bus, *groups);
337 
338     std::set<const Layout::GroupLayout*> assertedGroups;
339 
340     // Sleep
341     assertedGroups.insert(&groups->at(gBBUSleep));
342     assertMap(manager.getNewMap(assertedGroups),
343               {
344                   {bbu_ok, Layout::Action::Off},
345                   {bbu_fault, Layout::Action::Off},
346                   {bbu_lowv, Layout::Action::Off},
347                   {bbu_eol, Layout::Action::Off},
348               });
349 
350     // Fault
351     assertedGroups.insert(&groups->at(gBBUFault));
352     assertMap(manager.getNewMap(assertedGroups),
353               {
354                   {bbu_ok, Layout::Action::Off},
355                   {bbu_fault, Layout::Action::On},
356                   {bbu_lowv, Layout::Action::Off},
357                   {bbu_eol, Layout::Action::Off},
358               });
359 
360     // EOL
361     assertedGroups.insert(&groups->at(gBBUEOL));
362     assertMap(manager.getNewMap(assertedGroups),
363               {
364                   {bbu_ok, Layout::Action::Off},
365                   {bbu_fault, Layout::Action::On},
366                   {bbu_lowv, Layout::Action::Off},
367                   {bbu_eol, Layout::Action::On},
368               });
369 
370     // On + Locate
371     assertedGroups.insert(&groups->at(gBBUOnLocate));
372     assertMap(manager.getNewMap(assertedGroups),
373               {
374                   {bbu_ok, Layout::Action::On},
375                   {bbu_fault, Layout::Action::Blink},
376                   {bbu_lowv, Layout::Action::Off},
377                   {bbu_eol, Layout::Action::Off},
378               });
379 }
380