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