1 #include "libpldm/platform.h"
2 
3 #include "common/test/mocked_utils.hpp"
4 #include "libpldmresponder/pdr_utils.hpp"
5 #include "libpldmresponder/platform.hpp"
6 
7 #include <sdbusplus/test/sdbus_mock.hpp>
8 #include <sdeventplus/event.hpp>
9 
10 #include <gtest/gtest.h>
11 
12 using namespace pldm::responder;
13 using namespace pldm::responder::platform;
14 using namespace pldm::responder::pdr;
15 using namespace pldm::responder::pdr_utils;
16 
17 using ::testing::_;
18 using ::testing::Return;
19 using ::testing::StrEq;
20 
21 TEST(GeneratePDRByStateEffecter, testGoodJson)
22 {
23     MockdBusHandler mockedUtils;
24     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
25         .Times(5)
26         .WillRepeatedly(Return("foo.bar"));
27 
28     auto inPDRRepo = pldm_pdr_init();
29     auto outPDRRepo = pldm_pdr_init();
30     Repo outRepo(outPDRRepo);
31     auto event = sdeventplus::Event::get_default();
32     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
33                     nullptr, nullptr, nullptr, nullptr, event);
34     Repo inRepo(inPDRRepo);
35     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
36 
37     // 2 entries
38     ASSERT_EQ(outRepo.getRecordCount(), 2);
39 
40     // Check first PDR
41     pdr_utils::PdrEntry e;
42     auto record2 = pdr::getRecordByHandle(outRepo, 2, e);
43     ASSERT_NE(record2, nullptr);
44     pldm_state_effecter_pdr* pdr =
45         reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
46 
47     ASSERT_EQ(pdr->hdr.record_handle, 2);
48     ASSERT_EQ(pdr->hdr.version, 1);
49     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
50     ASSERT_EQ(pdr->hdr.record_change_num, 0);
51     ASSERT_EQ(pdr->hdr.length, 23);
52 
53     ASSERT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
54     ASSERT_EQ(pdr->effecter_id, 1);
55     ASSERT_EQ(pdr->entity_type, 33);
56     ASSERT_EQ(pdr->entity_instance, 0);
57     ASSERT_EQ(pdr->container_id, 0);
58     ASSERT_EQ(pdr->effecter_semantic_id, 0);
59     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
60     ASSERT_EQ(pdr->has_description_pdr, false);
61     ASSERT_EQ(pdr->composite_effecter_count, 2);
62     state_effecter_possible_states* states =
63         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
64     ASSERT_EQ(states->state_set_id, 196);
65     ASSERT_EQ(states->possible_states_size, 1);
66     bitfield8_t bf1{};
67     bf1.byte = 2;
68     ASSERT_EQ(states->states[0].byte, bf1.byte);
69 
70     const auto& [dbusMappings1, dbusValMaps1] =
71         handler.getDbusObjMaps(pdr->effecter_id);
72     ASSERT_EQ(dbusMappings1[0].objectPath, "/foo/bar");
73 
74     // Check second PDR
75     auto record3 = pdr::getRecordByHandle(outRepo, 3, e);
76     ASSERT_NE(record3, nullptr);
77     pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
78 
79     ASSERT_EQ(pdr->hdr.record_handle, 3);
80     ASSERT_EQ(pdr->hdr.version, 1);
81     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
82     ASSERT_EQ(pdr->hdr.record_change_num, 0);
83     ASSERT_EQ(pdr->hdr.length, 24);
84 
85     ASSERT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
86     ASSERT_EQ(pdr->effecter_id, 2);
87     ASSERT_EQ(pdr->entity_type, 100);
88     ASSERT_EQ(pdr->entity_instance, 0);
89     ASSERT_EQ(pdr->container_id, 0);
90     ASSERT_EQ(pdr->effecter_semantic_id, 0);
91     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
92     ASSERT_EQ(pdr->has_description_pdr, false);
93     ASSERT_EQ(pdr->composite_effecter_count, 2);
94     states =
95         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
96     ASSERT_EQ(states->state_set_id, 197);
97     ASSERT_EQ(states->possible_states_size, 1);
98     bf1.byte = 2;
99     ASSERT_EQ(states->states[0].byte, bf1.byte);
100     states = reinterpret_cast<state_effecter_possible_states*>(
101         pdr->possible_states + sizeof(state_effecter_possible_states));
102     ASSERT_EQ(states->state_set_id, 198);
103     ASSERT_EQ(states->possible_states_size, 2);
104     bitfield8_t bf2[2];
105     bf2[0].byte = 38;
106     bf2[1].byte = 128;
107     ASSERT_EQ(states->states[0].byte, bf2[0].byte);
108     ASSERT_EQ(states->states[1].byte, bf2[1].byte);
109 
110     const auto& [dbusMappings2, dbusValMaps2] =
111         handler.getDbusObjMaps(pdr->effecter_id);
112     ASSERT_EQ(dbusMappings2[0].objectPath, "/foo/bar");
113     ASSERT_EQ(dbusMappings2[1].objectPath, "/foo/bar");
114 
115     ASSERT_THROW(handler.getDbusObjMaps(0xDEAD), std::exception);
116 
117     pldm_pdr_destroy(inPDRRepo);
118     pldm_pdr_destroy(outPDRRepo);
119 }
120 
121 TEST(GeneratePDRByNumericEffecter, testGoodJson)
122 {
123     MockdBusHandler mockedUtils;
124     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
125         .Times(5)
126         .WillRepeatedly(Return("foo.bar"));
127 
128     auto inPDRRepo = pldm_pdr_init();
129     auto outPDRRepo = pldm_pdr_init();
130     Repo outRepo(outPDRRepo);
131     auto event = sdeventplus::Event::get_default();
132     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
133                     nullptr, nullptr, nullptr, nullptr, event);
134     Repo inRepo(inPDRRepo);
135     getRepoByType(inRepo, outRepo, PLDM_NUMERIC_EFFECTER_PDR);
136 
137     // 1 entries
138     ASSERT_EQ(outRepo.getRecordCount(), 1);
139 
140     // Check first PDR
141     pdr_utils::PdrEntry e;
142     auto record = pdr::getRecordByHandle(outRepo, 4, e);
143     ASSERT_NE(record, nullptr);
144 
145     pldm_numeric_effecter_value_pdr* pdr =
146         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
147     EXPECT_EQ(pdr->hdr.record_handle, 4);
148     EXPECT_EQ(pdr->hdr.version, 1);
149     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
150     EXPECT_EQ(pdr->hdr.record_change_num, 0);
151     EXPECT_EQ(pdr->hdr.length,
152               sizeof(pldm_numeric_effecter_value_pdr) - sizeof(pldm_pdr_hdr));
153 
154     EXPECT_EQ(pdr->effecter_id, 3);
155     EXPECT_EQ(pdr->effecter_data_size, 4);
156 
157     const auto& [dbusMappings, dbusValMaps] =
158         handler.getDbusObjMaps(pdr->effecter_id);
159     EXPECT_EQ(dbusMappings[0].objectPath, "/foo/bar");
160     EXPECT_EQ(dbusMappings[0].interface, "xyz.openbmc_project.Foo.Bar");
161     EXPECT_EQ(dbusMappings[0].propertyName, "propertyName");
162     EXPECT_EQ(dbusMappings[0].propertyType, "uint64_t");
163 
164     pldm_pdr_destroy(inPDRRepo);
165     pldm_pdr_destroy(outPDRRepo);
166 }
167 
168 TEST(GeneratePDR, testMalformedJson)
169 {
170     MockdBusHandler mockedUtils;
171     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
172         .Times(5)
173         .WillRepeatedly(Return("foo.bar"));
174 
175     auto inPDRRepo = pldm_pdr_init();
176     auto outPDRRepo = pldm_pdr_init();
177     Repo outRepo(outPDRRepo);
178     auto event = sdeventplus::Event::get_default();
179     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
180                     nullptr, nullptr, nullptr, nullptr, event);
181     Repo inRepo(inPDRRepo);
182     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
183 
184     ASSERT_EQ(outRepo.getRecordCount(), 2);
185     ASSERT_THROW(pdr_utils::readJson("./pdr_jsons/state_effecter/malformed"),
186                  std::exception);
187 
188     pldm_pdr_destroy(inPDRRepo);
189     pldm_pdr_destroy(outPDRRepo);
190 }
191 
192 TEST(findStateEffecterId, goodJson)
193 {
194     MockdBusHandler mockedUtils;
195     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
196         .Times(5)
197         .WillRepeatedly(Return("foo.bar"));
198 
199     auto inPDRRepo = pldm_pdr_init();
200     auto event = sdeventplus::Event::get_default();
201     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
202                     nullptr, nullptr, nullptr, nullptr, event);
203     uint16_t entityType = 33;
204     uint16_t entityInstance = 0;
205     uint16_t containerId = 0;
206     uint16_t stateSetId = 196;
207     auto effecterId = findStateEffecterId(inPDRRepo, entityType, entityInstance,
208                                           containerId, stateSetId, true);
209     ASSERT_EQ(effecterId, 1);
210     stateSetId = 300;
211     effecterId = findStateEffecterId(inPDRRepo, entityType, entityInstance,
212                                      containerId, stateSetId, true);
213     ASSERT_EQ(effecterId, PLDM_INVALID_EFFECTER_ID);
214     pldm_pdr_destroy(inPDRRepo);
215 }
216