blob: b13bf3f9216b9c3986995a9047787e87631e24d4 [file] [log] [blame]
Matt Spinler97f7abc2019-11-06 09:40:23 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlera906c942019-10-08 13:42:05 -050016#include "extensions/openpower-pels/fru_identity.hpp"
17
18#include <gtest/gtest.h>
19
20using namespace openpower::pels;
21using namespace openpower::pels::src;
22
23// Unflatten a FRUIdentity that is a HW FRU callout
24TEST(FRUIdentityTest, TestHardwareFRU)
25{
26 // Has PN, SN, CCIN
27 std::vector<uint8_t> data{'I', 'D', 0x1C, 0x1D, // type, size, flags
28 '1', '2', '3', '4', // PN
29 '5', '6', '7', 0x00, 'A', 'A', 'A', 'A', // CCIN
30 '1', '2', '3', '4', '5', '6', '7', '8', // SN
31 '9', 'A', 'B', 'C'};
32
33 Stream stream{data};
34
35 FRUIdentity fru{stream};
36
37 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::hardwareFRU);
38 EXPECT_EQ(fru.flattenedSize(), data.size());
Matt Spinlerba0ee002020-03-13 11:24:14 -050039 EXPECT_EQ(fru.type(), 0x4944);
Matt Spinlera906c942019-10-08 13:42:05 -050040
41 EXPECT_EQ(fru.getPN().value(), "1234567");
42 EXPECT_EQ(fru.getCCIN().value(), "AAAA");
43 EXPECT_EQ(fru.getSN().value(), "123456789ABC");
44 EXPECT_FALSE(fru.getMaintProc());
45
46 // Flatten
47 std::vector<uint8_t> newData;
48 Stream newStream{newData};
49 fru.flatten(newStream);
50 EXPECT_EQ(data, newData);
51}
52
53// Unflatten a FRUIdentity that is a Maintenance Procedure callout
54TEST(FRUIdentityTest, TestMaintProcedure)
55{
56 // Only contains the maintenance procedure
57 std::vector<uint8_t> data{
58 0x49, 0x44, 0x0C, 0x42, // type, size, flags
59 '1', '2', '3', '4', '5', '6', '7', 0x00 // Procedure
60 };
61
62 Stream stream{data};
63
64 FRUIdentity fru{stream};
65
66 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
67 EXPECT_EQ(fru.flattenedSize(), data.size());
68
69 EXPECT_EQ(fru.getMaintProc().value(), "1234567");
70 EXPECT_FALSE(fru.getPN());
71 EXPECT_FALSE(fru.getCCIN());
72 EXPECT_FALSE(fru.getSN());
73
74 // Flatten
75 std::vector<uint8_t> newData;
76 Stream newStream{newData};
77 fru.flatten(newStream);
78 EXPECT_EQ(data, newData);
79}
80
81// Try to unflatten garbage data
82TEST(FRUIdentityTest, BadDataTest)
83{
84 std::vector<uint8_t> data{0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85 0xFF, 0xFF, 0xFF, 0xFF};
86
87 Stream stream{data};
88
89 EXPECT_THROW(FRUIdentity fru{stream}, std::out_of_range);
90}
Matt Spinlerba0ee002020-03-13 11:24:14 -050091
92void testHWCallout(const std::string& pn, const std::string ccin,
93 const std::string& sn, const std::string& expectedPN,
94 const std::string& expectedCCIN,
95 const std::string& expectedSN)
96{
97 FRUIdentity fru{pn, ccin, sn};
98
99 EXPECT_EQ(fru.flattenedSize(), 28);
100 EXPECT_EQ(fru.type(), 0x4944);
101 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::hardwareFRU);
102 EXPECT_EQ(fru.getPN().value(), expectedPN);
103 EXPECT_EQ(fru.getCCIN().value(), expectedCCIN);
104 EXPECT_EQ(fru.getSN().value(), expectedSN);
105 EXPECT_FALSE(fru.getMaintProc());
106
107 // Flatten and unflatten, then compare again
108 std::vector<uint8_t> data;
109 Stream stream{data};
110 fru.flatten(stream);
111
112 EXPECT_EQ(data.size(), fru.flattenedSize());
113
114 stream.offset(0);
115 FRUIdentity newFRU{stream};
116
117 EXPECT_EQ(newFRU.flattenedSize(), fru.flattenedSize());
118 EXPECT_EQ(newFRU.type(), fru.type());
119 EXPECT_EQ(newFRU.failingComponentType(), fru.failingComponentType());
120 EXPECT_EQ(newFRU.getPN().value(), fru.getPN().value());
121 EXPECT_EQ(newFRU.getCCIN().value(), fru.getCCIN().value());
122 EXPECT_EQ(newFRU.getSN().value(), fru.getSN().value());
123 EXPECT_FALSE(newFRU.getMaintProc());
124}
125
126// Test the constructor that takes in a PN/SN/CCIN
127TEST(FRUIdentityTest, CreateHardwareCalloutTest)
128{
129 // The right sizes
130 testHWCallout("1234567", "1234", "123456789ABC",
131 // expected
132 "1234567", "1234", "123456789ABC");
133
134 // Too long
135 testHWCallout("1234567long", "1234long", "123456789ABClong",
136 // expected
137 "1234567", "1234", "123456789ABC");
138 // Too short
139 testHWCallout("11", "22", "333",
140 // expected
141 "11", "22", "333");
142
143 // empty
144 testHWCallout("", "", "",
145 // expected
146 "", "", "");
147
148 // Leading spaces in the part number will be stripped
149 testHWCallout(" 567", "1234", "123456789ABC",
150 // expected
151 "567", "1234", "123456789ABC");
152
153 // All spaces in the part number
154 testHWCallout(" ", "1234", "123456789ABC",
155 // expected
156 "", "1234", "123456789ABC");
157}
158
159// Test the constructor that takes in a maint procedure
160TEST(FRUIdentityTest, CreateProcedureCalloutTest)
161{
Matt Spinlera27e2e52020-04-09 11:06:11 -0500162 {
163 FRUIdentity fru{"no_vpd_for_fru"};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500164
Matt Spinlera27e2e52020-04-09 11:06:11 -0500165 EXPECT_EQ(fru.flattenedSize(), 12);
166 EXPECT_EQ(fru.type(), 0x4944);
167 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
168 EXPECT_EQ(fru.getMaintProc().value(), "BMCSP01");
169 EXPECT_FALSE(fru.getPN());
170 EXPECT_FALSE(fru.getCCIN());
171 EXPECT_FALSE(fru.getSN());
Matt Spinlerba0ee002020-03-13 11:24:14 -0500172
Matt Spinlera27e2e52020-04-09 11:06:11 -0500173 // Flatten and unflatten, then compare again
174 std::vector<uint8_t> data;
175 Stream stream{data};
176 fru.flatten(stream);
Matt Spinlerba0ee002020-03-13 11:24:14 -0500177
Matt Spinlera27e2e52020-04-09 11:06:11 -0500178 EXPECT_EQ(data.size(), fru.flattenedSize());
Matt Spinlerba0ee002020-03-13 11:24:14 -0500179
Matt Spinlera27e2e52020-04-09 11:06:11 -0500180 stream.offset(0);
181 FRUIdentity newFRU{stream};
Matt Spinlerba0ee002020-03-13 11:24:14 -0500182
Matt Spinlera27e2e52020-04-09 11:06:11 -0500183 EXPECT_EQ(newFRU.flattenedSize(), 12);
184 EXPECT_EQ(newFRU.type(), 0x4944);
185 EXPECT_EQ(newFRU.failingComponentType(), FRUIdentity::maintenanceProc);
186 EXPECT_EQ(newFRU.getMaintProc().value(), "BMCSP01");
187 EXPECT_FALSE(newFRU.getPN());
188 EXPECT_FALSE(newFRU.getCCIN());
189 EXPECT_FALSE(newFRU.getSN());
190 }
191
192 {
193 // Invalid maintenance procedure
194 FRUIdentity fru{"invalid"};
195
196 EXPECT_EQ(fru.flattenedSize(), 12);
197 EXPECT_EQ(fru.type(), 0x4944);
198 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::maintenanceProc);
199 EXPECT_EQ(fru.getMaintProc().value(), "INVALID");
200 EXPECT_FALSE(fru.getPN());
201 EXPECT_FALSE(fru.getCCIN());
202 EXPECT_FALSE(fru.getSN());
203 }
Matt Spinlerba0ee002020-03-13 11:24:14 -0500204}
Matt Spinler2b6dfa02020-04-09 11:39:05 -0500205
206// Test the constructor that takes in a symbolic FRU.
207TEST(FRUIdentityTest, CreateSymbolicFRUCalloutTest)
208{
209 // Symbolic FRU (not trusted)
210 {
211 FRUIdentity fru{"service_docs", false};
212
213 EXPECT_EQ(fru.flattenedSize(), 12);
214 EXPECT_EQ(fru.type(), 0x4944);
215 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::symbolicFRU);
216 EXPECT_EQ(fru.getPN().value(), "SVCDOCS");
217 EXPECT_FALSE(fru.getMaintProc());
218 EXPECT_FALSE(fru.getCCIN());
219 EXPECT_FALSE(fru.getSN());
220
221 // Flatten and unflatten, then compare again
222 std::vector<uint8_t> data;
223 Stream stream{data};
224 fru.flatten(stream);
225
226 EXPECT_EQ(data.size(), fru.flattenedSize());
227
228 stream.offset(0);
229 FRUIdentity newFRU{stream};
230
231 EXPECT_EQ(newFRU.flattenedSize(), 12);
232 EXPECT_EQ(newFRU.type(), 0x4944);
233 EXPECT_EQ(newFRU.failingComponentType(), FRUIdentity::symbolicFRU);
234 EXPECT_EQ(newFRU.getPN().value(), "SVCDOCS");
235 EXPECT_FALSE(newFRU.getMaintProc());
236 EXPECT_FALSE(newFRU.getCCIN());
237 EXPECT_FALSE(newFRU.getSN());
238 }
239
240 // Trusted symbolic FRU
241 {
242 FRUIdentity fru{"service_docs", true};
243
244 EXPECT_EQ(fru.flattenedSize(), 12);
245 EXPECT_EQ(fru.type(), 0x4944);
246 EXPECT_EQ(fru.failingComponentType(),
247 FRUIdentity::symbolicFRUTrustedLocCode);
248 EXPECT_EQ(fru.getPN().value(), "SVCDOCS");
249 EXPECT_FALSE(fru.getMaintProc());
250 EXPECT_FALSE(fru.getCCIN());
251 EXPECT_FALSE(fru.getSN());
252 }
253
254 // Invalid symbolic FRU
255 {
256 FRUIdentity fru{"garbage", false};
257
258 EXPECT_EQ(fru.flattenedSize(), 12);
259 EXPECT_EQ(fru.type(), 0x4944);
260 EXPECT_EQ(fru.failingComponentType(), FRUIdentity::symbolicFRU);
261 EXPECT_EQ(fru.getPN().value(), "INVALID");
262 EXPECT_FALSE(fru.getMaintProc());
263 EXPECT_FALSE(fru.getCCIN());
264 EXPECT_FALSE(fru.getSN());
265 }
266}