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