1 #include "common/utils.hpp"
2 #include "libpldmresponder/fru.hpp"
3 #include "libpldmresponder/fru_parser.hpp"
4 
5 #include <config.h>
6 #include <libpldm/pdr.h>
7 
8 #include <sdbusplus/message.hpp>
9 
10 #include <gtest/gtest.h>
11 
12 TEST(FruParser, allScenarios)
13 {
14     using namespace pldm::responder::fru_parser;
15 
16     FruParser parser{"./fru_jsons/good",
17                      "./fru_jsons/fru_master/fru_master.json"};
18 
19     // Get an item with a single PLDM FRU record
20     FruRecordInfos cpu{
21         {1,
22          1,
23          {{"xyz.openbmc_project.Inventory.Decorator.Asset", "Model", "string",
24            2},
25           {"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
26            "string", 3},
27           {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
28            "string", 4},
29           {"xyz.openbmc_project.Inventory.Decorator.Asset", "Manufacturer",
30            "string", 5},
31           {"xyz.openbmc_project.Inventory.Item", "PrettyName", "string", 8},
32           {"xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
33            "string", 11},
34           {"xyz.openbmc_project.Inventory.Decorator.Revision", "Version",
35            "string", 10}}},
36         {1,
37          1,
38          {{"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
39            "string", 3},
40           {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
41            "string", 4}}}};
42     auto cpuInfos =
43         parser.getRecordInfo("xyz.openbmc_project.Inventory.Item.Cpu");
44     ASSERT_EQ(cpuInfos.size(), 2);
45     ASSERT_EQ(cpu == cpuInfos, true);
46 
47     // Get an item type with 3 PLDM FRU records
48     auto boardInfos =
49         parser.getRecordInfo("xyz.openbmc_project.Inventory.Item.Board");
50     ASSERT_EQ(boardInfos.size(), 3);
51 
52     // D-Bus lookup info for FRU information
53     DBusLookupInfo lookupInfo{
54         "xyz.openbmc_project.Inventory.Manager",
55         "/xyz/openbmc_project/inventory",
56         {"xyz.openbmc_project.Inventory.Item.Chassis",
57          "xyz.openbmc_project.Inventory.Item.Board",
58          "xyz.openbmc_project.Inventory.Item.PCIeDevice",
59          "xyz.openbmc_project.Inventory.Item.Board.Motherboard",
60          "xyz.openbmc_project.Inventory.Item.Dimm",
61          "xyz.openbmc_project.Inventory.Item.Panel",
62          "xyz.openbmc_project.Inventory.Item.DiskBackplane",
63          "xyz.openbmc_project.Inventory.Item.Fan",
64          "xyz.openbmc_project.Inventory.Item.PowerSupply",
65          "xyz.openbmc_project.Inventory.Item.Battery",
66          "xyz.openbmc_project.Inventory.Item.Vrm",
67          "xyz.openbmc_project.Inventory.Item.Cpu",
68          "xyz.openbmc_project.Inventory.Item.Bmc",
69          "xyz.openbmc_project.Inventory.Item.Connector",
70          "xyz.openbmc_project.Inventory.Item.PCIeSlot",
71          "xyz.openbmc_project.Inventory.Item.System",
72          "xyz.openbmc_project.Inventory.Item.Tpm"}};
73     auto dbusInfo = parser.inventoryLookup();
74     ASSERT_EQ(dbusInfo == lookupInfo, true);
75 
76     ASSERT_THROW(
77         parser.getRecordInfo("xyz.openbmc_project.Inventory.Item.DIMM"),
78         std::exception);
79 }
80 
81 TEST(FruImpl, updateAssociationTreeTest)
82 {
83     using namespace pldm::responder;
84     using namespace pldm::responder::fru_parser;
85     using namespace pldm::responder::dbus;
86     std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> pdrRepo(
87         pldm_pdr_init(), pldm_pdr_destroy);
88     std::unique_ptr<pldm_entity_association_tree,
89                     decltype(&pldm_entity_association_tree_destroy)>
90         entityTree(pldm_entity_association_tree_init(),
91                    pldm_entity_association_tree_destroy);
92     std::unique_ptr<pldm_entity_association_tree,
93                     decltype(&pldm_entity_association_tree_destroy)>
94         bmcEntityTree(pldm_entity_association_tree_init(),
95                       pldm_entity_association_tree_destroy);
96 
97     ObjectValueTree objects{
98         {sdbusplus::message::object_path(
99              "/xyz/openbmc_project/inventory/system"),
100          {{"xyz.openbmc_project.Inventory.Item.System", {}}}},
101         {sdbusplus::message::object_path(
102              "/xyz/openbmc_project/inventory/system/chassis"),
103          {{"xyz.openbmc_project.Inventory.Item.Chassis", {}}}},
104         {sdbusplus::message::object_path(
105              "/xyz/openbmc_project/inventory/system/chassis/motherboard"),
106          {{"xyz.openbmc_project.Inventory.Item.Board.Motherboard", {}}}}};
107 
108     typedef struct test_pldm_entity_node
109     {
110         pldm_entity entity;
111         pldm_entity parent;
112         uint16_t host_container_id;
113         pldm_entity_node* first_child;
114         pldm_entity_node* next_sibling;
115         uint8_t association_type;
116     } test_pldm_entity_node;
117 
118     pldm::responder::FruImpl mockedFruHandler(
119         FRU_JSONS_DIR, "./fru_jsons/fru_master/fru_master.json", pdrRepo.get(),
120         entityTree.get(), bmcEntityTree.get());
121 
122     pldm_entity systemEntity{0x2d01, 1, 0};
123     pldm_entity chassisEntity{0x2d, 1, 1};
124     pldm_entity motherboardEntity{0x40, 1, 2};
125     pldm_entity panelEntity{0x45, 1, 3};
126 
127     dbus::InterfaceMap systemIface{
128         {"xyz.openbmc_project.Inventory.Item.System", {}}};
129     dbus::InterfaceMap chassisIface{
130         {"xyz.openbmc_project.Inventory.Item.Chassis", {}}};
131     dbus::InterfaceMap motherboardIface{
132         {"xyz.openbmc_project.Inventory.Item.Board.Motherboard", {}}};
133 
134     mockedFruHandler.updateAssociationTree(
135         objects, "/xyz/openbmc_project/inventory/system/chassis/motherboard");
136 
137     pldm_entity_node* node =
138         pldm_entity_association_tree_find(entityTree.get(), &systemEntity);
139     EXPECT_TRUE(node != NULL);
140 
141     node = pldm_entity_association_tree_find(entityTree.get(), &chassisEntity);
142     ASSERT_TRUE(node != NULL);
143     test_pldm_entity_node* test_node = (test_pldm_entity_node*)node;
144     EXPECT_TRUE((test_node->parent).entity_type == systemEntity.entity_type);
145 
146     node =
147         pldm_entity_association_tree_find(entityTree.get(), &motherboardEntity);
148     ASSERT_TRUE(node != NULL);
149     test_node = (test_pldm_entity_node*)node;
150     EXPECT_TRUE((test_node->parent).entity_type == chassisEntity.entity_type);
151 
152     node = pldm_entity_association_tree_find(entityTree.get(), &panelEntity);
153     EXPECT_TRUE(node == NULL);
154 }
155 
156 TEST(FruImpl, entityByObjectPath)
157 {
158     using namespace pldm::responder::dbus;
159     std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> pdrRepo(
160         pldm_pdr_init(), pldm_pdr_destroy);
161     std::unique_ptr<pldm_entity_association_tree,
162                     decltype(&pldm_entity_association_tree_destroy)>
163         entityTree(pldm_entity_association_tree_init(),
164                    pldm_entity_association_tree_destroy);
165     std::unique_ptr<pldm_entity_association_tree,
166                     decltype(&pldm_entity_association_tree_destroy)>
167         bmcEntityTree(pldm_entity_association_tree_init(),
168                       pldm_entity_association_tree_destroy);
169 
170     InterfaceMap iface = {{"xyz.openbmc_project.Inventory.Item.Chassis", {}}};
171     pldm::responder::FruImpl mockedFruHandler(
172         FRU_JSONS_DIR, "./fru_jsons/fru_master/fru_master.json", pdrRepo.get(),
173         entityTree.get(), bmcEntityTree.get());
174 
175     // Good path
176     auto entityPtr = mockedFruHandler.getEntityByObjectPath(iface);
177     pldm_entity entity = *entityPtr;
178     EXPECT_TRUE(entity.entity_type == 45);
179     // Bad Path
180     InterfaceMap invalidIface = {
181         {"xyz.openbmc_project.Inventory.Item.Motherboard", {}}};
182     entityPtr = mockedFruHandler.getEntityByObjectPath(invalidIface);
183     ASSERT_TRUE(!entityPtr);
184 }
185