blob: 1a5f81f3ad0d0831e1aa55b1ad84302bd1683bc0 [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 Spinlerb8323632019-09-20 15:11:04 -050016#include "elog_entry.hpp"
Matt Spinler131870c2019-09-25 13:29:04 -050017#include "extensions/openpower-pels/generic.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -050018#include "extensions/openpower-pels/pel.hpp"
Matt Spinleraa659472019-10-23 09:26:48 -050019#include "mocks.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -050020#include "pel_utils.hpp"
21
22#include <filesystem>
23#include <fstream>
24
25#include <gtest/gtest.h>
26
27namespace fs = std::filesystem;
28using namespace openpower::pels;
29
30class PELTest : public CleanLogID
31{
32};
33
34TEST_F(PELTest, FlattenTest)
35{
Matt Spinler42828bd2019-10-11 10:39:30 -050036 auto data = pelDataFactory(TestPELType::pelSimple);
Matt Spinler42828bd2019-10-11 10:39:30 -050037 auto pel = std::make_unique<PEL>(data);
Matt Spinlercb6b0592019-07-16 15:58:51 -050038
39 // Check a few fields
40 EXPECT_TRUE(pel->valid());
41 EXPECT_EQ(pel->id(), 0x80818283);
42 EXPECT_EQ(pel->plid(), 0x50515253);
Matt Spinler97d19b42019-10-29 11:34:03 -050043 EXPECT_EQ(pel->userHeader().subsystem(), 0x10);
44 EXPECT_EQ(pel->userHeader().actionFlags(), 0x80C0);
Matt Spinlercb6b0592019-07-16 15:58:51 -050045
46 // Test that data in == data out
47 auto flattenedData = pel->data();
Matt Spinlerf1b46ff2020-01-22 14:10:04 -060048 EXPECT_EQ(data, flattenedData);
49 EXPECT_EQ(flattenedData.size(), pel->size());
Matt Spinlercb6b0592019-07-16 15:58:51 -050050}
51
52TEST_F(PELTest, CommitTimeTest)
53{
Matt Spinler42828bd2019-10-11 10:39:30 -050054 auto data = pelDataFactory(TestPELType::pelSimple);
55 auto pel = std::make_unique<PEL>(data);
Matt Spinlercb6b0592019-07-16 15:58:51 -050056
57 auto origTime = pel->commitTime();
58 pel->setCommitTime();
59 auto newTime = pel->commitTime();
60
Matt Spinlerf1b46ff2020-01-22 14:10:04 -060061 EXPECT_NE(origTime, newTime);
Matt Spinlercb6b0592019-07-16 15:58:51 -050062
63 // Make a new PEL and check new value is still there
64 auto newData = pel->data();
65 auto newPel = std::make_unique<PEL>(newData);
Matt Spinlerf1b46ff2020-01-22 14:10:04 -060066 EXPECT_EQ(newTime, newPel->commitTime());
Matt Spinlercb6b0592019-07-16 15:58:51 -050067}
68
69TEST_F(PELTest, AssignIDTest)
70{
Matt Spinler42828bd2019-10-11 10:39:30 -050071 auto data = pelDataFactory(TestPELType::pelSimple);
72 auto pel = std::make_unique<PEL>(data);
Matt Spinlercb6b0592019-07-16 15:58:51 -050073
74 auto origID = pel->id();
75 pel->assignID();
76 auto newID = pel->id();
77
Matt Spinlerf1b46ff2020-01-22 14:10:04 -060078 EXPECT_NE(origID, newID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050079
80 // Make a new PEL and check new value is still there
81 auto newData = pel->data();
82 auto newPel = std::make_unique<PEL>(newData);
Matt Spinlerf1b46ff2020-01-22 14:10:04 -060083 EXPECT_EQ(newID, newPel->id());
Matt Spinlercb6b0592019-07-16 15:58:51 -050084}
85
86TEST_F(PELTest, WithLogIDTest)
87{
Matt Spinler42828bd2019-10-11 10:39:30 -050088 auto data = pelDataFactory(TestPELType::pelSimple);
89 auto pel = std::make_unique<PEL>(data, 0x42);
Matt Spinlercb6b0592019-07-16 15:58:51 -050090
91 EXPECT_TRUE(pel->valid());
92 EXPECT_EQ(pel->obmcLogID(), 0x42);
93}
94
95TEST_F(PELTest, InvalidPELTest)
96{
Matt Spinler42828bd2019-10-11 10:39:30 -050097 auto data = pelDataFactory(TestPELType::pelSimple);
Matt Spinlercb6b0592019-07-16 15:58:51 -050098
99 // Too small
Matt Spinler42828bd2019-10-11 10:39:30 -0500100 data.resize(PrivateHeader::flattenedSize());
Matt Spinlercb6b0592019-07-16 15:58:51 -0500101
Matt Spinler42828bd2019-10-11 10:39:30 -0500102 auto pel = std::make_unique<PEL>(data);
Matt Spinlercb6b0592019-07-16 15:58:51 -0500103
Matt Spinler97d19b42019-10-29 11:34:03 -0500104 EXPECT_TRUE(pel->privateHeader().valid());
105 EXPECT_FALSE(pel->userHeader().valid());
Matt Spinlercb6b0592019-07-16 15:58:51 -0500106 EXPECT_FALSE(pel->valid());
107
Matt Spinlercb6b0592019-07-16 15:58:51 -0500108 // Now corrupt the private header
Matt Spinler42828bd2019-10-11 10:39:30 -0500109 data = pelDataFactory(TestPELType::pelSimple);
110 data.at(0) = 0;
111 pel = std::make_unique<PEL>(data);
Matt Spinlercb6b0592019-07-16 15:58:51 -0500112
Matt Spinler97d19b42019-10-29 11:34:03 -0500113 EXPECT_FALSE(pel->privateHeader().valid());
114 EXPECT_TRUE(pel->userHeader().valid());
Matt Spinlercb6b0592019-07-16 15:58:51 -0500115 EXPECT_FALSE(pel->valid());
116}
117
118TEST_F(PELTest, EmptyDataTest)
119{
120 std::vector<uint8_t> data;
121 auto pel = std::make_unique<PEL>(data);
122
Matt Spinler97d19b42019-10-29 11:34:03 -0500123 EXPECT_FALSE(pel->privateHeader().valid());
124 EXPECT_FALSE(pel->userHeader().valid());
Matt Spinlercb6b0592019-07-16 15:58:51 -0500125 EXPECT_FALSE(pel->valid());
126}
Matt Spinlerb8323632019-09-20 15:11:04 -0500127
128TEST_F(PELTest, CreateFromRegistryTest)
129{
130 message::Entry regEntry;
131 uint64_t timestamp = 5;
132
133 regEntry.name = "test";
134 regEntry.subsystem = 5;
135 regEntry.actionFlags = 0xC000;
Matt Spinlerbd716f02019-10-15 10:54:11 -0500136 regEntry.src.type = 0xBD;
137 regEntry.src.reasonCode = 0x1234;
Matt Spinlerb8323632019-09-20 15:11:04 -0500138
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600139 std::vector<std::string> data{"KEY1=VALUE1"};
140 AdditionalData ad{data};
Matt Spinleraa659472019-10-23 09:26:48 -0500141 MockDataInterface dataIface;
Matt Spinlerbd716f02019-10-15 10:54:11 -0500142
Matt Spinleraa659472019-10-23 09:26:48 -0500143 PEL pel{regEntry, 42, timestamp, phosphor::logging::Entry::Level::Error, ad,
144 dataIface};
Matt Spinlerb8323632019-09-20 15:11:04 -0500145
146 EXPECT_TRUE(pel.valid());
Matt Spinler97d19b42019-10-29 11:34:03 -0500147 EXPECT_EQ(pel.privateHeader().obmcLogID(), 42);
148 EXPECT_EQ(pel.userHeader().severity(), 0x40);
Matt Spinlerb8323632019-09-20 15:11:04 -0500149
Matt Spinlerbd716f02019-10-15 10:54:11 -0500150 EXPECT_EQ(pel.primarySRC().value()->asciiString(),
151 "BD051234 ");
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600152
153 // Check that certain optional sections have been created
154 size_t mtmsCount = 0;
155 size_t euhCount = 0;
156 size_t udCount = 0;
157
158 for (const auto& section : pel.optionalSections())
159 {
160 if (section->header().id ==
161 static_cast<uint16_t>(SectionID::failingMTMS))
162 {
163 mtmsCount++;
164 }
165 else if (section->header().id ==
166 static_cast<uint16_t>(SectionID::extendedUserHeader))
167 {
168 euhCount++;
169 }
170 else if (section->header().id ==
171 static_cast<uint16_t>(SectionID::userData))
172 {
173 udCount++;
174 }
175 }
176
177 EXPECT_EQ(mtmsCount, 1);
178 EXPECT_EQ(euhCount, 1);
179 EXPECT_EQ(udCount, 2); // AD section and sysInfo section
Matt Spinlerb8323632019-09-20 15:11:04 -0500180}
Matt Spinler131870c2019-09-25 13:29:04 -0500181
182// Test that we'll create Generic optional sections for sections that
183// there aren't explicit classes for.
184TEST_F(PELTest, GenericSectionTest)
185{
Matt Spinler42828bd2019-10-11 10:39:30 -0500186 auto data = pelDataFactory(TestPELType::pelSimple);
Matt Spinler131870c2019-09-25 13:29:04 -0500187
188 std::vector<uint8_t> section1{0x58, 0x58, // ID 'XX'
189 0x00, 0x18, // Size
190 0x01, 0x02, // version, subtype
191 0x03, 0x04, // comp ID
192
193 // some data
194 0x20, 0x30, 0x05, 0x09, 0x11, 0x1E, 0x1, 0x63,
195 0x20, 0x31, 0x06, 0x0F, 0x09, 0x22, 0x3A,
196 0x00};
197
198 std::vector<uint8_t> section2{
199 0x59, 0x59, // ID 'YY'
200 0x00, 0x20, // Size
201 0x01, 0x02, // version, subtype
202 0x03, 0x04, // comp ID
203
204 // some data
205 0x20, 0x30, 0x05, 0x09, 0x11, 0x1E, 0x1, 0x63, 0x20, 0x31, 0x06, 0x0F,
206 0x09, 0x22, 0x3A, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
207
208 // Add the new sections at the end
Matt Spinler42828bd2019-10-11 10:39:30 -0500209 data.insert(data.end(), section1.begin(), section1.end());
210 data.insert(data.end(), section2.begin(), section2.end());
Matt Spinler131870c2019-09-25 13:29:04 -0500211
212 // Increment the section count
Matt Spinler42828bd2019-10-11 10:39:30 -0500213 data.at(27) += 2;
214 auto origData = data;
Matt Spinler131870c2019-09-25 13:29:04 -0500215
Matt Spinler42828bd2019-10-11 10:39:30 -0500216 PEL pel{data};
Matt Spinler131870c2019-09-25 13:29:04 -0500217
218 const auto& sections = pel.optionalSections();
219
220 bool foundXX = false;
221 bool foundYY = false;
222
223 // Check that we can find these 2 Generic sections
224 for (const auto& section : sections)
225 {
226 if (section->header().id == 0x5858)
227 {
228 foundXX = true;
229 EXPECT_NE(dynamic_cast<Generic*>(section.get()), nullptr);
230 }
231 else if (section->header().id == 0x5959)
232 {
233 foundYY = true;
234 EXPECT_NE(dynamic_cast<Generic*>(section.get()), nullptr);
235 }
236 }
237
238 EXPECT_TRUE(foundXX);
239 EXPECT_TRUE(foundYY);
Matt Spinler07eefc52019-09-26 11:18:26 -0500240
241 // Now flatten and check
242 auto newData = pel.data();
243
244 EXPECT_EQ(origData, newData);
Matt Spinler131870c2019-09-25 13:29:04 -0500245}
246
247// Test that an invalid section will still get a Generic object
248TEST_F(PELTest, InvalidGenericTest)
249{
Matt Spinler42828bd2019-10-11 10:39:30 -0500250 auto data = pelDataFactory(TestPELType::pelSimple);
Matt Spinler131870c2019-09-25 13:29:04 -0500251
252 // Not a valid section
253 std::vector<uint8_t> section1{0x01, 0x02, 0x03};
254
Matt Spinler42828bd2019-10-11 10:39:30 -0500255 data.insert(data.end(), section1.begin(), section1.end());
Matt Spinler131870c2019-09-25 13:29:04 -0500256
257 // Increment the section count
Matt Spinler42828bd2019-10-11 10:39:30 -0500258 data.at(27) += 1;
Matt Spinler131870c2019-09-25 13:29:04 -0500259
Matt Spinler42828bd2019-10-11 10:39:30 -0500260 PEL pel{data};
Matt Spinler131870c2019-09-25 13:29:04 -0500261 EXPECT_FALSE(pel.valid());
262
263 const auto& sections = pel.optionalSections();
264
265 bool foundGeneric = false;
266 for (const auto& section : sections)
267 {
268 if (dynamic_cast<Generic*>(section.get()) != nullptr)
269 {
270 foundGeneric = true;
271 EXPECT_EQ(section->valid(), false);
272 break;
273 }
274 }
275
276 EXPECT_TRUE(foundGeneric);
277}
Matt Spinlerafa857c2019-10-24 13:03:46 -0500278
279// Create a UserData section out of AdditionalData
280TEST_F(PELTest, MakeUDSectionTest)
281{
282 std::vector<std::string> ad{"KEY1=VALUE1", "KEY2=VALUE2", "KEY3=VALUE3",
283 "ESEL=TEST"};
284 AdditionalData additionalData{ad};
285
286 auto ud = util::makeADUserDataSection(additionalData);
287
288 EXPECT_TRUE(ud->valid());
289 EXPECT_EQ(ud->header().id, 0x5544);
290 EXPECT_EQ(ud->header().version, 0x01);
291 EXPECT_EQ(ud->header().subType, 0x01);
292 EXPECT_EQ(ud->header().componentID, 0x2000);
293
294 const auto& d = ud->data();
295
296 std::string jsonString{d.begin(), d.end()};
Matt Spinler53407be2019-11-18 09:16:31 -0600297
298 std::string expectedJSON =
Matt Spinlerafa857c2019-10-24 13:03:46 -0500299 R"({"KEY1":"VALUE1","KEY2":"VALUE2","KEY3":"VALUE3"})";
Matt Spinler53407be2019-11-18 09:16:31 -0600300
301 // The actual data is null padded to a 4B boundary.
302 std::vector<uint8_t> expectedData;
303 expectedData.resize(52, '\0');
304 memcpy(expectedData.data(), expectedJSON.data(), expectedJSON.size());
305
306 EXPECT_EQ(d, expectedData);
Matt Spinlerafa857c2019-10-24 13:03:46 -0500307
308 // Ensure we can read this as JSON
309 auto newJSON = nlohmann::json::parse(jsonString);
310 EXPECT_EQ(newJSON["KEY1"], "VALUE1");
311 EXPECT_EQ(newJSON["KEY2"], "VALUE2");
312 EXPECT_EQ(newJSON["KEY3"], "VALUE3");
Matt Spinler97d19b42019-10-29 11:34:03 -0500313}
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600314
315// Create the UserData section that contains system info
316TEST_F(PELTest, MakeSysInfoSectionTest)
317{
318 MockDataInterface dataIface;
319
320 std::string pid = "_PID=" + std::to_string(getpid());
321 std::vector<std::string> ad{pid};
322 AdditionalData additionalData{ad};
323
324 auto ud = util::makeSysInfoUserDataSection(additionalData, dataIface);
325
326 EXPECT_TRUE(ud->valid());
327 EXPECT_EQ(ud->header().id, 0x5544);
328 EXPECT_EQ(ud->header().version, 0x01);
329 EXPECT_EQ(ud->header().subType, 0x01);
330 EXPECT_EQ(ud->header().componentID, 0x2000);
331
332 // Pull out the JSON data and check it.
333 const auto& d = ud->data();
334 std::string jsonString{d.begin(), d.end()};
335 auto json = nlohmann::json::parse(jsonString);
336
337 // Ensure the 'Process Name' entry contains 'pel_test'
338 auto name = json["Process Name"].get<std::string>();
339 EXPECT_NE(name.find("pel_test"), std::string::npos);
340}