blob: b966344aaaf76e7b35902e9528e24ff6f22ce34e [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"
17#include "pel_utils.hpp"
18
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080019#include <fstream>
20
Matt Spinlerf9bae182019-10-09 13:37:38 -050021#include <gtest/gtest.h>
22
23using namespace openpower::pels;
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080024namespace fs = std::filesystem;
Matt Spinlerf9bae182019-10-09 13:37:38 -050025
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080026const auto testRegistry = R"(
27{
28"PELs":
29[
30 {
31 "Name": "xyz.openbmc_project.Error.Test",
32 "Subsystem": "bmc_firmware",
33 "SRC":
34 {
35 "ReasonCode": "0xABCD",
36 "Words6To9":
37 {
38 "6":
39 {
40 "Description": "Component ID",
41 "AdditionalDataPropSource": "COMPID"
42 },
43 "7":
44 {
45 "Description": "Failure count",
46 "AdditionalDataPropSource": "FREQUENCY"
47 },
48 "8":
49 {
50 "Description": "Time period",
51 "AdditionalDataPropSource": "DURATION"
52 },
53 "9":
54 {
55 "Description": "Error code",
56 "AdditionalDataPropSource": "ERRORCODE"
57 }
58 }
59 },
60 "Documentation":
61 {
62 "Description": "A Component Fault",
63 "Message": "Comp %1 failed %2 times over %3 secs with ErrorCode %4",
64 "MessageArgSources":
65 [
66 "SRCWord6", "SRCWord7", "SRCWord8", "SRCWord9"
67 ]
68 }
69 }
70]
71}
72)";
73
74class SRCTest : public ::testing::Test
75{
76 protected:
77 static void SetUpTestCase()
78 {
79 char path[] = "/tmp/srctestXXXXXX";
80 regDir = mkdtemp(path);
81 }
82
83 static void TearDownTestCase()
84 {
85 fs::remove_all(regDir);
86 }
87
88 static std::string writeData(const char* data)
89 {
90 fs::path path = regDir / "registry.json";
91 std::ofstream stream{path};
92 stream << data;
93 return path;
94 }
95
96 static fs::path regDir;
97};
98
99fs::path SRCTest::regDir{};
100
101TEST_F(SRCTest, UnflattenFlattenTestNoCallouts)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500102{
Matt Spinler42828bd2019-10-11 10:39:30 -0500103 auto data = pelDataFactory(TestPELType::primarySRCSection);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500104
105 Stream stream{data};
106 SRC src{stream};
107
108 EXPECT_TRUE(src.valid());
109
110 EXPECT_EQ(src.header().id, 0x5053);
Matt Spinlerf1b46ff2020-01-22 14:10:04 -0600111 EXPECT_EQ(src.header().size, 0x50);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500112 EXPECT_EQ(src.header().version, 0x01);
113 EXPECT_EQ(src.header().subType, 0x01);
114 EXPECT_EQ(src.header().componentID, 0x0202);
115
116 EXPECT_EQ(src.version(), 0x02);
117 EXPECT_EQ(src.flags(), 0x00);
118 EXPECT_EQ(src.hexWordCount(), 9);
119 EXPECT_EQ(src.size(), 0x48);
120
121 const auto& hexwords = src.hexwordData();
Matt Spinlerbd716f02019-10-15 10:54:11 -0500122 EXPECT_EQ(0x02020255, hexwords[0]);
123 EXPECT_EQ(0x03030310, hexwords[1]);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500124 EXPECT_EQ(0x04040404, hexwords[2]);
125 EXPECT_EQ(0x05050505, hexwords[3]);
126 EXPECT_EQ(0x06060606, hexwords[4]);
127 EXPECT_EQ(0x07070707, hexwords[5]);
128 EXPECT_EQ(0x08080808, hexwords[6]);
129 EXPECT_EQ(0x09090909, hexwords[7]);
130
131 EXPECT_EQ(src.asciiString(), "BD8D5678 ");
132 EXPECT_FALSE(src.callouts());
133
134 // Flatten
135 std::vector<uint8_t> newData;
136 Stream newStream{newData};
137
138 src.flatten(newStream);
139 EXPECT_EQ(data, newData);
140}
141
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800142TEST_F(SRCTest, UnflattenFlattenTest2Callouts)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500143{
Matt Spinler42828bd2019-10-11 10:39:30 -0500144 auto data = pelDataFactory(TestPELType::primarySRCSection2Callouts);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500145
146 Stream stream{data};
147 SRC src{stream};
148
149 EXPECT_TRUE(src.valid());
Matt Spinlerbd716f02019-10-15 10:54:11 -0500150 EXPECT_EQ(src.flags(), 0x01); // Additional sections within the SRC.
Matt Spinlerf9bae182019-10-09 13:37:38 -0500151
152 // Spot check the SRC fields, but they're the same as above
153 EXPECT_EQ(src.asciiString(), "BD8D5678 ");
154
155 // There should be 2 callouts
156 const auto& calloutsSection = src.callouts();
157 ASSERT_TRUE(calloutsSection);
158 const auto& callouts = calloutsSection->callouts();
159 EXPECT_EQ(callouts.size(), 2);
160
161 // spot check that each callout has the right substructures
162 EXPECT_TRUE(callouts.front()->fruIdentity());
163 EXPECT_FALSE(callouts.front()->pceIdentity());
164 EXPECT_FALSE(callouts.front()->mru());
165
166 EXPECT_TRUE(callouts.back()->fruIdentity());
167 EXPECT_TRUE(callouts.back()->pceIdentity());
168 EXPECT_TRUE(callouts.back()->mru());
169
170 // Flatten
171 std::vector<uint8_t> newData;
172 Stream newStream{newData};
173
174 src.flatten(newStream);
175 EXPECT_EQ(data, newData);
176}
Matt Spinlerbd716f02019-10-15 10:54:11 -0500177
178// Create an SRC from the message registry
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800179TEST_F(SRCTest, CreateTestNoCallouts)
Matt Spinlerbd716f02019-10-15 10:54:11 -0500180{
181 message::Entry entry;
182 entry.src.type = 0xBD;
183 entry.src.reasonCode = 0xABCD;
184 entry.subsystem = 0x42;
185 entry.src.powerFault = true;
186 entry.src.hexwordADFields = {{5, "TEST1"}, // Not a user defined word
187 {6, "TEST1"},
188 {7, "TEST2"},
189 {8, "TEST3"},
190 {9, "TEST4"}};
191
192 // Values for the SRC words pointed to above
193 std::vector<std::string> adData{"TEST1=0x12345678", "TEST2=12345678",
194 "TEST3=0XDEF", "TEST4=Z"};
195 AdditionalData ad{adData};
196 SRC src{entry, ad};
197
198 EXPECT_TRUE(src.valid());
199 EXPECT_TRUE(src.isPowerFaultEvent());
200 EXPECT_EQ(src.size(), baseSRCSize);
201
202 const auto& hexwords = src.hexwordData();
203
204 // The spec always refers to SRC words 2 - 9, and as the hexwordData()
205 // array index starts at 0 use the math in the [] below to make it easier
206 // to tell what is being accessed.
207 EXPECT_EQ(hexwords[2 - 2] & 0xF0000000, 0); // Partition dump status
208 EXPECT_EQ(hexwords[2 - 2] & 0x00F00000, 0); // Partition boot type
209 EXPECT_EQ(hexwords[2 - 2] & 0x000000FF, 0x55); // SRC format
210 EXPECT_EQ(hexwords[3 - 2] & 0x000000FF, 0x10); // BMC position
211
212 // Validate more fields here as the code starts filling them in.
213
214 // Ensure hex word 5 wasn't allowed to be set to TEST1's contents
215 EXPECT_EQ(hexwords[5 - 2], 0);
216
217 // The user defined hex word fields specifed in the additional data.
218 EXPECT_EQ(hexwords[6 - 2], 0x12345678); // TEST1
219 EXPECT_EQ(hexwords[7 - 2], 12345678); // TEST2
220 EXPECT_EQ(hexwords[8 - 2], 0xdef); // TEST3
221 EXPECT_EQ(hexwords[9 - 2], 0); // TEST4, but can't convert a 'Z'
222
223 EXPECT_EQ(src.asciiString(), "BD42ABCD ");
224
225 // No callouts
226 EXPECT_FALSE(src.callouts());
227
228 // May as well spot check the flatten/unflatten
229 std::vector<uint8_t> data;
230 Stream stream{data};
231 src.flatten(stream);
232
233 stream.offset(0);
234 SRC newSRC{stream};
235
236 EXPECT_TRUE(newSRC.valid());
237 EXPECT_EQ(newSRC.isPowerFaultEvent(), src.isPowerFaultEvent());
238 EXPECT_EQ(newSRC.asciiString(), src.asciiString());
239 EXPECT_FALSE(newSRC.callouts());
240}
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800241
242// Test the getErrorDetails function
243TEST_F(SRCTest, MessageSubstitutionTest)
244{
245 auto path = SRCTest::writeData(testRegistry);
246 message::Registry registry{path};
247 auto entry = registry.lookup("0xABCD", message::LookupType::reasonCode);
248
249 std::vector<std::string> adData{"COMPID=0x1", "FREQUENCY=0x4",
250 "DURATION=30", "ERRORCODE=0x01ABCDEF"};
251 AdditionalData ad{adData};
252
253 SRC src{*entry, ad};
254 EXPECT_TRUE(src.valid());
255
256 auto errorDetails = src.getErrorDetails(registry, DetailLevel::message);
257 ASSERT_TRUE(errorDetails);
258 EXPECT_EQ(
259 errorDetails.value(),
260 "Comp 0x1 failed 0x4 times over 0x1E secs with ErrorCode 0x1ABCDEF");
261}