xref: /openbmc/phosphor-logging/test/openpower-pels/fru_identity_test.cpp (revision 40fb54935ce7367636a7156039396ee91cc4d5e2)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright 2019 IBM Corporation
3 
4 #include "extensions/openpower-pels/fru_identity.hpp"
5 
6 #include <gtest/gtest.h>
7 
8 using namespace openpower::pels;
9 using namespace openpower::pels::src;
10 
11 // Unflatten a FRUIdentity that is a HW FRU callout
TEST(FRUIdentityTest,TestHardwareFRU)12 TEST(FRUIdentityTest, TestHardwareFRU)
13 {
14     // Has PN, SN, CCIN
15     std::vector<uint8_t> data{'I', 'D', 0x1C, 0x1D, // type, size, flags
16                               '1', '2', '3',  '4',  // PN
17                               '5', '6', '7',  0x00, 'A', 'A', 'A', 'A', // CCIN
18                               '1', '2', '3',  '4',  '5', '6', '7', '8', // SN
19                               '9', 'A', 'B',  'C'};
20 
21     Stream stream{data};
22 
23     FRUIdentity fru{stream};
24 
25     EXPECT_EQ(fru.failingComponentType(), FRUIdentity::hardwareFRU);
26     EXPECT_EQ(fru.flattenedSize(), data.size());
27     EXPECT_EQ(fru.type(), 0x4944);
28 
29     EXPECT_EQ(fru.getPN().value(), "1234567");
30     EXPECT_EQ(fru.getCCIN().value(), "AAAA");
31     EXPECT_EQ(fru.getSN().value(), "123456789ABC");
32     EXPECT_FALSE(fru.getMaintProc());
33 
34     // Flatten
35     std::vector<uint8_t> newData;
36     Stream newStream{newData};
37     fru.flatten(newStream);
38     EXPECT_EQ(data, newData);
39 }
40 
41 // Unflatten a FRUIdentity that is a Maintenance Procedure callout
TEST(FRUIdentityTest,TestMaintProcedure)42 TEST(FRUIdentityTest, TestMaintProcedure)
43 {
44     // Only contains the maintenance procedure
45     std::vector<uint8_t> data{
46         0x49, 0x44, 0x0C, 0x42,                     // type, size, flags
47         '1',  '2',  '3',  '4',  '5', '6', '7', 0x00 // Procedure
48     };
49 
50     Stream stream{data};
51 
52     FRUIdentity fru{stream};
53 
54     EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
55     EXPECT_EQ(fru.flattenedSize(), data.size());
56 
57     EXPECT_EQ(fru.getMaintProc().value(), "1234567");
58     EXPECT_FALSE(fru.getPN());
59     EXPECT_FALSE(fru.getCCIN());
60     EXPECT_FALSE(fru.getSN());
61 
62     // Flatten
63     std::vector<uint8_t> newData;
64     Stream newStream{newData};
65     fru.flatten(newStream);
66     EXPECT_EQ(data, newData);
67 }
68 
69 // Try to unflatten garbage data
TEST(FRUIdentityTest,BadDataTest)70 TEST(FRUIdentityTest, BadDataTest)
71 {
72     std::vector<uint8_t> data{0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
73                               0xFF, 0xFF, 0xFF, 0xFF};
74 
75     Stream stream{data};
76 
77     EXPECT_THROW(FRUIdentity fru{stream}, std::out_of_range);
78 }
79 
testHWCallout(const std::string & pn,const std::string & ccin,const std::string & sn,const std::string & expectedPN,const std::string & expectedCCIN,const std::string & expectedSN)80 void testHWCallout(const std::string& pn, const std::string& ccin,
81                    const std::string& sn, const std::string& expectedPN,
82                    const std::string& expectedCCIN,
83                    const std::string& expectedSN)
84 {
85     FRUIdentity fru{pn, ccin, sn};
86 
87     EXPECT_EQ(fru.flattenedSize(), 28);
88     EXPECT_EQ(fru.type(), 0x4944);
89     EXPECT_EQ(fru.failingComponentType(), FRUIdentity::hardwareFRU);
90     EXPECT_EQ(fru.getPN().value(), expectedPN);
91     EXPECT_EQ(fru.getCCIN().value(), expectedCCIN);
92     EXPECT_EQ(fru.getSN().value(), expectedSN);
93     EXPECT_FALSE(fru.getMaintProc());
94 
95     // Flatten and unflatten, then compare again
96     std::vector<uint8_t> data;
97     Stream stream{data};
98     fru.flatten(stream);
99 
100     EXPECT_EQ(data.size(), fru.flattenedSize());
101 
102     stream.offset(0);
103     FRUIdentity newFRU{stream};
104 
105     EXPECT_EQ(newFRU.flattenedSize(), fru.flattenedSize());
106     EXPECT_EQ(newFRU.type(), fru.type());
107     EXPECT_EQ(newFRU.failingComponentType(), fru.failingComponentType());
108     EXPECT_EQ(newFRU.getPN().value(), fru.getPN().value());
109     EXPECT_EQ(newFRU.getCCIN().value(), fru.getCCIN().value());
110     EXPECT_EQ(newFRU.getSN().value(), fru.getSN().value());
111     EXPECT_FALSE(newFRU.getMaintProc());
112 }
113 
114 // Test the constructor that takes in a PN/SN/CCIN
TEST(FRUIdentityTest,CreateHardwareCalloutTest)115 TEST(FRUIdentityTest, CreateHardwareCalloutTest)
116 {
117     // The right sizes
118     testHWCallout("1234567", "1234", "123456789ABC",
119                   // expected
120                   "1234567", "1234", "123456789ABC");
121 
122     // Too long
123     testHWCallout("1234567long", "1234long", "123456789ABClong",
124                   // expected
125                   "1234567", "1234", "123456789ABC");
126     // Too short
127     testHWCallout("11", "22", "333",
128                   // expected
129                   "11", "22", "333");
130 
131     // empty
132     testHWCallout("", "", "",
133                   // expected
134                   "", "", "");
135 
136     // Leading spaces in the part number will be stripped
137     testHWCallout("    567", "1234", "123456789ABC",
138                   // expected
139                   "567", "1234", "123456789ABC");
140 
141     // All spaces in the part number
142     testHWCallout("       ", "1234", "123456789ABC",
143                   // expected
144                   "", "1234", "123456789ABC");
145 }
146 
147 // Test the constructor that takes in a maint procedure
TEST(FRUIdentityTest,CreateProcedureCalloutTest)148 TEST(FRUIdentityTest, CreateProcedureCalloutTest)
149 {
150     {
151         FRUIdentity fru{"bmc_code"};
152 
153         EXPECT_EQ(fru.flattenedSize(), 12);
154         EXPECT_EQ(fru.type(), 0x4944);
155         EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
156         EXPECT_EQ(fru.getMaintProc().value(), "BMC0001");
157         EXPECT_FALSE(fru.getPN());
158         EXPECT_FALSE(fru.getCCIN());
159         EXPECT_FALSE(fru.getSN());
160 
161         // Flatten and unflatten, then compare again
162         std::vector<uint8_t> data;
163         Stream stream{data};
164         fru.flatten(stream);
165 
166         EXPECT_EQ(data.size(), fru.flattenedSize());
167 
168         stream.offset(0);
169         FRUIdentity newFRU{stream};
170 
171         EXPECT_EQ(newFRU.flattenedSize(), 12);
172         EXPECT_EQ(newFRU.type(), 0x4944);
173         EXPECT_EQ(newFRU.failingComponentType(), FRUIdentity::maintenanceProc);
174         EXPECT_EQ(newFRU.getMaintProc().value(), "BMC0001");
175         EXPECT_FALSE(newFRU.getPN());
176         EXPECT_FALSE(newFRU.getCCIN());
177         EXPECT_FALSE(newFRU.getSN());
178     }
179 
180     {
181         // Invalid maintenance procedure
182         FRUIdentity fru{"invalid"};
183 
184         EXPECT_EQ(fru.flattenedSize(), 12);
185         EXPECT_EQ(fru.type(), 0x4944);
186         EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
187         EXPECT_EQ(fru.getMaintProc().value(), "INVALID");
188         EXPECT_FALSE(fru.getPN());
189         EXPECT_FALSE(fru.getCCIN());
190         EXPECT_FALSE(fru.getSN());
191     }
192 
193     {
194         // Raw maintenance procedure
195         FRUIdentity fru{"BMCXXXXLONG", CalloutValueType::raw};
196         EXPECT_EQ(fru.getMaintProc().value(), "BMCXXXX");
197     }
198 }
199 
200 // Test the constructor that takes in a symbolic FRU.
TEST(FRUIdentityTest,CreateSymbolicFRUCalloutTest)201 TEST(FRUIdentityTest, CreateSymbolicFRUCalloutTest)
202 {
203     // Symbolic FRU (not trusted)
204     {
205         FRUIdentity fru{"service_docs", false};
206 
207         EXPECT_EQ(fru.flattenedSize(), 12);
208         EXPECT_EQ(fru.type(), 0x4944);
209         EXPECT_EQ(fru.failingComponentType(), FRUIdentity::symbolicFRU);
210         EXPECT_EQ(fru.getPN().value(), "SVCDOCS");
211         EXPECT_FALSE(fru.getMaintProc());
212         EXPECT_FALSE(fru.getCCIN());
213         EXPECT_FALSE(fru.getSN());
214 
215         // Flatten and unflatten, then compare again
216         std::vector<uint8_t> data;
217         Stream stream{data};
218         fru.flatten(stream);
219 
220         EXPECT_EQ(data.size(), fru.flattenedSize());
221 
222         stream.offset(0);
223         FRUIdentity newFRU{stream};
224 
225         EXPECT_EQ(newFRU.flattenedSize(), 12);
226         EXPECT_EQ(newFRU.type(), 0x4944);
227         EXPECT_EQ(newFRU.failingComponentType(), FRUIdentity::symbolicFRU);
228         EXPECT_EQ(newFRU.getPN().value(), "SVCDOCS");
229         EXPECT_FALSE(newFRU.getMaintProc());
230         EXPECT_FALSE(newFRU.getCCIN());
231         EXPECT_FALSE(newFRU.getSN());
232     }
233 
234     // Trusted symbolic FRU
235     {
236         FRUIdentity fru{"service_docs", true};
237 
238         EXPECT_EQ(fru.flattenedSize(), 12);
239         EXPECT_EQ(fru.type(), 0x4944);
240         EXPECT_EQ(fru.failingComponentType(),
241                   FRUIdentity::symbolicFRUTrustedLocCode);
242         EXPECT_EQ(fru.getPN().value(), "SVCDOCS");
243         EXPECT_FALSE(fru.getMaintProc());
244         EXPECT_FALSE(fru.getCCIN());
245         EXPECT_FALSE(fru.getSN());
246     }
247 
248     // Invalid symbolic FRU
249     {
250         FRUIdentity fru{"garbage", false};
251 
252         EXPECT_EQ(fru.flattenedSize(), 12);
253         EXPECT_EQ(fru.type(), 0x4944);
254         EXPECT_EQ(fru.failingComponentType(), FRUIdentity::symbolicFRU);
255         EXPECT_EQ(fru.getPN().value(), "INVALID");
256         EXPECT_FALSE(fru.getMaintProc());
257         EXPECT_FALSE(fru.getCCIN());
258         EXPECT_FALSE(fru.getSN());
259     }
260 
261     // Raw symbolic FRU
262     {
263         FRUIdentity fru{"SOMEFRULONG", CalloutValueType::raw, false};
264 
265         EXPECT_EQ(fru.getPN().value(), "SOMEFRU");
266     }
267 }
268