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