blob: f7f84e4c3503f875d5422ff2be47d7dedc63d620 [file] [log] [blame]
Alexander Hansen40fb5492025-10-28 17:56:12 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2019 IBM Corporation
3
Matt Spinlera906c942019-10-08 13:42:05 -05004#include "extensions/openpower-pels/fru_identity.hpp"
5
6#include <gtest/gtest.h>
7
8using namespace openpower::pels;
9using namespace openpower::pels::src;
10
11// Unflatten a FRUIdentity that is a HW FRU callout
12TEST(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());
Matt Spinlerba0ee002020-03-13 11:24:14 -050027 EXPECT_EQ(fru.type(), 0x4944);
Matt Spinlera906c942019-10-08 13:42:05 -050028
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
42TEST(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
70TEST(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}
Matt Spinlerba0ee002020-03-13 11:24:14 -050079
Matt Spinlerbe952d22022-07-01 11:30:11 -050080void testHWCallout(const std::string& pn, const std::string& ccin,
Matt Spinlerba0ee002020-03-13 11:24:14 -050081 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
115TEST(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
148TEST(FRUIdentityTest, CreateProcedureCalloutTest)
149{
Matt Spinlera27e2e52020-04-09 11:06:11 -0500150 {
Matt Spinler479b6922021-08-17 16:34:59 -0500151 FRUIdentity fru{"bmc_code"};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500152
Matt Spinlera27e2e52020-04-09 11:06:11 -0500153 EXPECT_EQ(fru.flattenedSize(), 12);
154 EXPECT_EQ(fru.type(), 0x4944);
155 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
Matt Spinlerea2873d2021-08-18 10:35:40 -0500156 EXPECT_EQ(fru.getMaintProc().value(), "BMC0001");
Matt Spinlera27e2e52020-04-09 11:06:11 -0500157 EXPECT_FALSE(fru.getPN());
158 EXPECT_FALSE(fru.getCCIN());
159 EXPECT_FALSE(fru.getSN());
Matt Spinlerba0ee002020-03-13 11:24:14 -0500160
Matt Spinlera27e2e52020-04-09 11:06:11 -0500161 // Flatten and unflatten, then compare again
162 std::vector<uint8_t> data;
163 Stream stream{data};
164 fru.flatten(stream);
Matt Spinlerba0ee002020-03-13 11:24:14 -0500165
Matt Spinlera27e2e52020-04-09 11:06:11 -0500166 EXPECT_EQ(data.size(), fru.flattenedSize());
Matt Spinlerba0ee002020-03-13 11:24:14 -0500167
Matt Spinlera27e2e52020-04-09 11:06:11 -0500168 stream.offset(0);
169 FRUIdentity newFRU{stream};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500170
Matt Spinlera27e2e52020-04-09 11:06:11 -0500171 EXPECT_EQ(newFRU.flattenedSize(), 12);
172 EXPECT_EQ(newFRU.type(), 0x4944);
173 EXPECT_EQ(newFRU.failingComponentType(), FRUIdentity::maintenanceProc);
Matt Spinlerea2873d2021-08-18 10:35:40 -0500174 EXPECT_EQ(newFRU.getMaintProc().value(), "BMC0001");
Matt Spinlera27e2e52020-04-09 11:06:11 -0500175 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 }
Matt Spinler468aab52020-08-13 11:04:31 -0500192
193 {
194 // Raw maintenance procedure
Matt Spinlerea2873d2021-08-18 10:35:40 -0500195 FRUIdentity fru{"BMCXXXXLONG", CalloutValueType::raw};
196 EXPECT_EQ(fru.getMaintProc().value(), "BMCXXXX");
Matt Spinler468aab52020-08-13 11:04:31 -0500197 }
Matt Spinlerba0ee002020-03-13 11:24:14 -0500198}
Matt Spinler2b6dfa02020-04-09 11:39:05 -0500199
200// Test the constructor that takes in a symbolic FRU.
201TEST(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 }
Matt Spinler468aab52020-08-13 11:04:31 -0500260
261 // Raw symbolic FRU
262 {
263 FRUIdentity fru{"SOMEFRULONG", CalloutValueType::raw, false};
264
265 EXPECT_EQ(fru.getPN().value(), "SOMEFRU");
266 }
Matt Spinler2b6dfa02020-04-09 11:39:05 -0500267}