blob: 383c7e181f8763659f72c1a49f0c9fe1df150446 [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 Spinlerf9bae182019-10-09 13:37:38 -050016#include "extensions/openpower-pels/src.hpp"
Matt Spinler075e5ba2020-02-21 15:46:00 -060017#include "mocks.hpp"
Matt Spinlerf9bae182019-10-09 13:37:38 -050018#include "pel_utils.hpp"
19
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080020#include <fstream>
21
Matt Spinlerf9bae182019-10-09 13:37:38 -050022#include <gtest/gtest.h>
23
24using namespace openpower::pels;
Matt Spinler075e5ba2020-02-21 15:46:00 -060025using ::testing::NiceMock;
26using ::testing::Return;
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080027namespace fs = std::filesystem;
Matt Spinlerf9bae182019-10-09 13:37:38 -050028
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080029const auto testRegistry = R"(
30{
31"PELs":
32[
33 {
34 "Name": "xyz.openbmc_project.Error.Test",
35 "Subsystem": "bmc_firmware",
36 "SRC":
37 {
38 "ReasonCode": "0xABCD",
39 "Words6To9":
40 {
41 "6":
42 {
43 "Description": "Component ID",
44 "AdditionalDataPropSource": "COMPID"
45 },
46 "7":
47 {
48 "Description": "Failure count",
49 "AdditionalDataPropSource": "FREQUENCY"
50 },
51 "8":
52 {
53 "Description": "Time period",
54 "AdditionalDataPropSource": "DURATION"
55 },
56 "9":
57 {
58 "Description": "Error code",
59 "AdditionalDataPropSource": "ERRORCODE"
60 }
61 }
62 },
63 "Documentation":
64 {
65 "Description": "A Component Fault",
66 "Message": "Comp %1 failed %2 times over %3 secs with ErrorCode %4",
67 "MessageArgSources":
68 [
69 "SRCWord6", "SRCWord7", "SRCWord8", "SRCWord9"
70 ]
71 }
72 }
73]
74}
75)";
76
77class SRCTest : public ::testing::Test
78{
79 protected:
80 static void SetUpTestCase()
81 {
82 char path[] = "/tmp/srctestXXXXXX";
83 regDir = mkdtemp(path);
84 }
85
86 static void TearDownTestCase()
87 {
88 fs::remove_all(regDir);
89 }
90
91 static std::string writeData(const char* data)
92 {
93 fs::path path = regDir / "registry.json";
94 std::ofstream stream{path};
95 stream << data;
96 return path;
97 }
98
99 static fs::path regDir;
100};
101
102fs::path SRCTest::regDir{};
103
104TEST_F(SRCTest, UnflattenFlattenTestNoCallouts)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500105{
Matt Spinler42828bd2019-10-11 10:39:30 -0500106 auto data = pelDataFactory(TestPELType::primarySRCSection);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500107
108 Stream stream{data};
109 SRC src{stream};
110
111 EXPECT_TRUE(src.valid());
112
113 EXPECT_EQ(src.header().id, 0x5053);
Matt Spinlerf1b46ff2020-01-22 14:10:04 -0600114 EXPECT_EQ(src.header().size, 0x50);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500115 EXPECT_EQ(src.header().version, 0x01);
116 EXPECT_EQ(src.header().subType, 0x01);
117 EXPECT_EQ(src.header().componentID, 0x0202);
118
119 EXPECT_EQ(src.version(), 0x02);
120 EXPECT_EQ(src.flags(), 0x00);
121 EXPECT_EQ(src.hexWordCount(), 9);
122 EXPECT_EQ(src.size(), 0x48);
123
124 const auto& hexwords = src.hexwordData();
Matt Spinlerbd716f02019-10-15 10:54:11 -0500125 EXPECT_EQ(0x02020255, hexwords[0]);
126 EXPECT_EQ(0x03030310, hexwords[1]);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500127 EXPECT_EQ(0x04040404, hexwords[2]);
128 EXPECT_EQ(0x05050505, hexwords[3]);
129 EXPECT_EQ(0x06060606, hexwords[4]);
130 EXPECT_EQ(0x07070707, hexwords[5]);
131 EXPECT_EQ(0x08080808, hexwords[6]);
132 EXPECT_EQ(0x09090909, hexwords[7]);
133
134 EXPECT_EQ(src.asciiString(), "BD8D5678 ");
135 EXPECT_FALSE(src.callouts());
136
137 // Flatten
138 std::vector<uint8_t> newData;
139 Stream newStream{newData};
140
141 src.flatten(newStream);
142 EXPECT_EQ(data, newData);
143}
144
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800145TEST_F(SRCTest, UnflattenFlattenTest2Callouts)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500146{
Matt Spinler42828bd2019-10-11 10:39:30 -0500147 auto data = pelDataFactory(TestPELType::primarySRCSection2Callouts);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500148
149 Stream stream{data};
150 SRC src{stream};
151
152 EXPECT_TRUE(src.valid());
Matt Spinlerbd716f02019-10-15 10:54:11 -0500153 EXPECT_EQ(src.flags(), 0x01); // Additional sections within the SRC.
Matt Spinlerf9bae182019-10-09 13:37:38 -0500154
155 // Spot check the SRC fields, but they're the same as above
156 EXPECT_EQ(src.asciiString(), "BD8D5678 ");
157
158 // There should be 2 callouts
159 const auto& calloutsSection = src.callouts();
160 ASSERT_TRUE(calloutsSection);
161 const auto& callouts = calloutsSection->callouts();
162 EXPECT_EQ(callouts.size(), 2);
163
164 // spot check that each callout has the right substructures
165 EXPECT_TRUE(callouts.front()->fruIdentity());
166 EXPECT_FALSE(callouts.front()->pceIdentity());
167 EXPECT_FALSE(callouts.front()->mru());
168
169 EXPECT_TRUE(callouts.back()->fruIdentity());
170 EXPECT_TRUE(callouts.back()->pceIdentity());
171 EXPECT_TRUE(callouts.back()->mru());
172
173 // Flatten
174 std::vector<uint8_t> newData;
175 Stream newStream{newData};
176
177 src.flatten(newStream);
178 EXPECT_EQ(data, newData);
179}
Matt Spinlerbd716f02019-10-15 10:54:11 -0500180
181// Create an SRC from the message registry
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800182TEST_F(SRCTest, CreateTestNoCallouts)
Matt Spinlerbd716f02019-10-15 10:54:11 -0500183{
184 message::Entry entry;
185 entry.src.type = 0xBD;
186 entry.src.reasonCode = 0xABCD;
187 entry.subsystem = 0x42;
188 entry.src.powerFault = true;
189 entry.src.hexwordADFields = {{5, "TEST1"}, // Not a user defined word
190 {6, "TEST1"},
191 {7, "TEST2"},
192 {8, "TEST3"},
193 {9, "TEST4"}};
194
195 // Values for the SRC words pointed to above
196 std::vector<std::string> adData{"TEST1=0x12345678", "TEST2=12345678",
197 "TEST3=0XDEF", "TEST4=Z"};
198 AdditionalData ad{adData};
Matt Spinler075e5ba2020-02-21 15:46:00 -0600199 NiceMock<MockDataInterface> dataIface;
200
201 EXPECT_CALL(dataIface, getMotherboardCCIN).WillOnce(Return("ABCD"));
202
203 SRC src{entry, ad, dataIface};
Matt Spinlerbd716f02019-10-15 10:54:11 -0500204
205 EXPECT_TRUE(src.valid());
206 EXPECT_TRUE(src.isPowerFaultEvent());
207 EXPECT_EQ(src.size(), baseSRCSize);
208
209 const auto& hexwords = src.hexwordData();
210
211 // The spec always refers to SRC words 2 - 9, and as the hexwordData()
212 // array index starts at 0 use the math in the [] below to make it easier
213 // to tell what is being accessed.
214 EXPECT_EQ(hexwords[2 - 2] & 0xF0000000, 0); // Partition dump status
215 EXPECT_EQ(hexwords[2 - 2] & 0x00F00000, 0); // Partition boot type
216 EXPECT_EQ(hexwords[2 - 2] & 0x000000FF, 0x55); // SRC format
217 EXPECT_EQ(hexwords[3 - 2] & 0x000000FF, 0x10); // BMC position
Matt Spinler075e5ba2020-02-21 15:46:00 -0600218 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0xABCD0000); // Motherboard CCIN
Matt Spinlerbd716f02019-10-15 10:54:11 -0500219
220 // Validate more fields here as the code starts filling them in.
221
222 // Ensure hex word 5 wasn't allowed to be set to TEST1's contents
223 EXPECT_EQ(hexwords[5 - 2], 0);
224
225 // The user defined hex word fields specifed in the additional data.
226 EXPECT_EQ(hexwords[6 - 2], 0x12345678); // TEST1
227 EXPECT_EQ(hexwords[7 - 2], 12345678); // TEST2
228 EXPECT_EQ(hexwords[8 - 2], 0xdef); // TEST3
229 EXPECT_EQ(hexwords[9 - 2], 0); // TEST4, but can't convert a 'Z'
230
231 EXPECT_EQ(src.asciiString(), "BD42ABCD ");
232
233 // No callouts
234 EXPECT_FALSE(src.callouts());
235
236 // May as well spot check the flatten/unflatten
237 std::vector<uint8_t> data;
238 Stream stream{data};
239 src.flatten(stream);
240
241 stream.offset(0);
242 SRC newSRC{stream};
243
244 EXPECT_TRUE(newSRC.valid());
245 EXPECT_EQ(newSRC.isPowerFaultEvent(), src.isPowerFaultEvent());
246 EXPECT_EQ(newSRC.asciiString(), src.asciiString());
247 EXPECT_FALSE(newSRC.callouts());
248}
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800249
Matt Spinler075e5ba2020-02-21 15:46:00 -0600250// Test when the CCIN string isn't a 4 character number
251TEST_F(SRCTest, BadCCINTest)
252{
253 message::Entry entry;
254 entry.src.type = 0xBD;
255 entry.src.reasonCode = 0xABCD;
256 entry.subsystem = 0x42;
257 entry.src.powerFault = false;
258
259 std::vector<std::string> adData{};
260 AdditionalData ad{adData};
261 NiceMock<MockDataInterface> dataIface;
262
263 // First it isn't a number, then it is too long,
264 // then it is empty.
265 EXPECT_CALL(dataIface, getMotherboardCCIN)
266 .WillOnce(Return("X"))
267 .WillOnce(Return("12345"))
268 .WillOnce(Return(""));
269
270 // The CCIN in the first half should still be 0 each time.
271 {
272 SRC src{entry, ad, dataIface};
273 EXPECT_TRUE(src.valid());
274 const auto& hexwords = src.hexwordData();
275 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
276 }
277
278 {
279 SRC src{entry, ad, dataIface};
280 EXPECT_TRUE(src.valid());
281 const auto& hexwords = src.hexwordData();
282 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
283 }
284
285 {
286 SRC src{entry, ad, dataIface};
287 EXPECT_TRUE(src.valid());
288 const auto& hexwords = src.hexwordData();
289 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
290 }
291}
292
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800293// Test the getErrorDetails function
294TEST_F(SRCTest, MessageSubstitutionTest)
295{
296 auto path = SRCTest::writeData(testRegistry);
297 message::Registry registry{path};
298 auto entry = registry.lookup("0xABCD", message::LookupType::reasonCode);
299
300 std::vector<std::string> adData{"COMPID=0x1", "FREQUENCY=0x4",
301 "DURATION=30", "ERRORCODE=0x01ABCDEF"};
302 AdditionalData ad{adData};
Matt Spinler075e5ba2020-02-21 15:46:00 -0600303 NiceMock<MockDataInterface> dataIface;
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800304
Matt Spinler075e5ba2020-02-21 15:46:00 -0600305 SRC src{*entry, ad, dataIface};
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800306 EXPECT_TRUE(src.valid());
307
308 auto errorDetails = src.getErrorDetails(registry, DetailLevel::message);
309 ASSERT_TRUE(errorDetails);
310 EXPECT_EQ(
311 errorDetails.value(),
312 "Comp 0x1 failed 0x4 times over 0x1E secs with ErrorCode 0x1ABCDEF");
313}