blob: 3036f3035809612a42d1f1763013b211a353738e [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 Spinler89fa0822019-07-17 13:54:30 -050016#include "extensions/openpower-pels/manager.hpp"
17#include "log_manager.hpp"
18#include "pel_utils.hpp"
19
20#include <fstream>
21#include <regex>
Matt Spinlera34ab722019-12-16 10:39:32 -060022#include <xyz/openbmc_project/Common/error.hpp>
Matt Spinler89fa0822019-07-17 13:54:30 -050023
24#include <gtest/gtest.h>
25
26using namespace openpower::pels;
27namespace fs = std::filesystem;
28
29class ManagerTest : public CleanPELFiles
30{
31};
32
33fs::path makeTempDir()
34{
35 char path[] = "/tmp/tempnameXXXXXX";
36 std::filesystem::path dir = mkdtemp(path);
37 return dir;
38}
39
Matt Spinler67456c22019-10-21 12:22:49 -050040std::optional<fs::path> findAnyPELInRepo()
41{
42 // PELs are named <timestamp>_<ID>
43 std::regex expr{"\\d+_\\d+"};
44
45 for (auto& f : fs::directory_iterator(getPELRepoPath() / "logs"))
46 {
47 if (std::regex_search(f.path().string(), expr))
48 {
49 return f.path();
50 }
51 }
52 return std::nullopt;
53}
54
Matt Spinler89fa0822019-07-17 13:54:30 -050055// Test that using the RAWPEL=<file> with the Manager::create() call gets
56// a PEL saved in the repository.
57TEST_F(ManagerTest, TestCreateWithPEL)
58{
59 auto bus = sdbusplus::bus::new_default();
60 phosphor::logging::internal::Manager logManager(bus, "logging_path");
Matt Spinlerc8705e22019-09-11 12:36:07 -050061 std::unique_ptr<DataInterfaceBase> dataIface =
62 std::make_unique<DataInterface>(bus);
Matt Spinler89fa0822019-07-17 13:54:30 -050063
Matt Spinlerc8705e22019-09-11 12:36:07 -050064 openpower::pels::Manager manager{logManager, std::move(dataIface)};
Matt Spinler89fa0822019-07-17 13:54:30 -050065
66 // Create a PEL, write it to a file, and pass that filename into
67 // the create function.
Matt Spinler42828bd2019-10-11 10:39:30 -050068 auto data = pelDataFactory(TestPELType::pelSimple);
Matt Spinler89fa0822019-07-17 13:54:30 -050069
70 fs::path pelFilename = makeTempDir() / "rawpel";
71 std::ofstream pelFile{pelFilename};
Matt Spinler42828bd2019-10-11 10:39:30 -050072 pelFile.write(reinterpret_cast<const char*>(data.data()), data.size());
Matt Spinler89fa0822019-07-17 13:54:30 -050073 pelFile.close();
74
75 std::string adItem = "RAWPEL=" + pelFilename.string();
76 std::vector<std::string> additionalData{adItem};
77 std::vector<std::string> associations;
78
Matt Spinler367144c2019-09-19 15:33:52 -050079 manager.create("error message", 42, 0,
80 phosphor::logging::Entry::Level::Error, additionalData,
Matt Spinler89fa0822019-07-17 13:54:30 -050081 associations);
82
Matt Spinler67456c22019-10-21 12:22:49 -050083 // Find the file in the PEL repository directory
84 auto pelPathInRepo = findAnyPELInRepo();
Matt Spinler89fa0822019-07-17 13:54:30 -050085
Matt Spinler67456c22019-10-21 12:22:49 -050086 EXPECT_TRUE(pelPathInRepo);
Matt Spinler89fa0822019-07-17 13:54:30 -050087
Matt Spinler475e5742019-07-18 16:09:49 -050088 // Now remove it based on its OpenBMC event log ID
89 manager.erase(42);
90
Matt Spinler67456c22019-10-21 12:22:49 -050091 pelPathInRepo = findAnyPELInRepo();
Matt Spinler475e5742019-07-18 16:09:49 -050092
Matt Spinler67456c22019-10-21 12:22:49 -050093 EXPECT_FALSE(pelPathInRepo);
Matt Spinler475e5742019-07-18 16:09:49 -050094
Matt Spinler89fa0822019-07-17 13:54:30 -050095 fs::remove_all(pelFilename.parent_path());
96}
Matt Spinler67456c22019-10-21 12:22:49 -050097
98// Test that the message registry can be used to build a PEL.
99TEST_F(ManagerTest, TestCreateWithMessageRegistry)
100{
101 const auto registry = R"(
102{
103 "PELs":
104 [
105 {
106 "Name": "xyz.openbmc_project.Error.Test",
107 "Subsystem": "power_supply",
108 "ActionFlags": ["service_action", "report"],
109 "SRC":
110 {
111 "ReasonCode": "0x2030"
112 }
113 }
114 ]
115}
116)";
117
Matt Spinlerd4ffb652019-11-12 14:16:14 -0600118 auto path = getMessageRegistryPath();
119 fs::create_directories(path);
120 path /= "message_registry.json";
121
Matt Spinler67456c22019-10-21 12:22:49 -0500122 std::ofstream registryFile{path};
123 registryFile << registry;
124 registryFile.close();
125
126 auto bus = sdbusplus::bus::new_default();
127 phosphor::logging::internal::Manager logManager(bus, "logging_path");
128
129 std::unique_ptr<DataInterfaceBase> dataIface =
130 std::make_unique<DataInterface>(logManager.getBus());
131
132 openpower::pels::Manager manager{logManager, std::move(dataIface)};
133
134 std::vector<std::string> additionalData;
135 std::vector<std::string> associations;
136
137 // Create the event log to create the PEL from.
138 manager.create("xyz.openbmc_project.Error.Test", 33, 0,
139 phosphor::logging::Entry::Level::Error, additionalData,
140 associations);
141
142 // Ensure a PEL was created in the repository
143 auto pelFile = findAnyPELInRepo();
144 ASSERT_TRUE(pelFile);
145
146 auto data = readPELFile(*pelFile);
147 PEL pel(*data);
148
149 // Spot check it. Other testcases cover the details.
150 EXPECT_TRUE(pel.valid());
151 EXPECT_EQ(pel.obmcLogID(), 33);
152 EXPECT_EQ(pel.primarySRC().value()->asciiString(),
153 "BD612030 ");
154
155 // Remove it
156 manager.erase(33);
157 pelFile = findAnyPELInRepo();
158 EXPECT_FALSE(pelFile);
159
160 // Create an event log that can't be found in the registry.
161 manager.create("xyz.openbmc_project.Error.Foo", 33, 0,
162 phosphor::logging::Entry::Level::Error, additionalData,
163 associations);
164
165 // Currently, no PEL should be created. Eventually, a 'missing registry
166 // entry' PEL will be there.
167 pelFile = findAnyPELInRepo();
168 EXPECT_FALSE(pelFile);
169}
Matt Spinlera34ab722019-12-16 10:39:32 -0600170
171TEST_F(ManagerTest, TestDBusMethods)
172{
173 auto bus = sdbusplus::bus::new_default();
174 phosphor::logging::internal::Manager logManager(bus, "logging_path");
175 std::unique_ptr<DataInterfaceBase> dataIface =
176 std::make_unique<DataInterface>(bus);
177
178 Manager manager{logManager, std::move(dataIface)};
179
180 // Create a PEL, write it to a file, and pass that filename into
181 // the create function so there's one in the repo.
182 auto data = pelDataFactory(TestPELType::pelSimple);
183
184 fs::path pelFilename = makeTempDir() / "rawpel";
185 std::ofstream pelFile{pelFilename};
186 pelFile.write(reinterpret_cast<const char*>(data.data()), data.size());
187 pelFile.close();
188
189 std::string adItem = "RAWPEL=" + pelFilename.string();
190 std::vector<std::string> additionalData{adItem};
191 std::vector<std::string> associations;
192
193 manager.create("error message", 42, 0,
194 phosphor::logging::Entry::Level::Error, additionalData,
195 associations);
196
197 // getPELFromOBMCID
198 auto newData = manager.getPELFromOBMCID(42);
199 EXPECT_EQ(newData.size(), data.size());
200
201 // Read the PEL to get the ID for later
202 PEL pel{newData};
203 auto id = pel.id();
204
205 EXPECT_THROW(
206 manager.getPELFromOBMCID(id + 1),
207 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
208
209 // getPEL
210 auto unixfd = manager.getPEL(id);
211
212 // Get the size
213 struct stat s;
214 int r = fstat(unixfd, &s);
215 ASSERT_EQ(r, 0);
216 auto size = s.st_size;
217
218 // Open the FD and check the contents
219 FILE* fp = fdopen(unixfd, "r");
220 ASSERT_NE(fp, nullptr);
221
222 std::vector<uint8_t> fdData;
223 fdData.resize(size);
224 r = fread(fdData.data(), 1, size, fp);
225 EXPECT_EQ(r, size);
226
227 EXPECT_EQ(newData, fdData);
228
229 fclose(fp);
230
231 EXPECT_THROW(
232 manager.getPEL(id + 1),
233 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
234
235 // hostAck
236 manager.hostAck(id);
237
238 EXPECT_THROW(
239 manager.hostAck(id + 1),
240 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
241
242 // hostReject
243 manager.hostReject(id, Manager::RejectionReason::BadPEL);
244 manager.hostReject(id, Manager::RejectionReason::HostFull);
245
246 EXPECT_THROW(
247 manager.hostReject(id + 1, Manager::RejectionReason::BadPEL),
248 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
249
250 fs::remove_all(pelFilename.parent_path());
251}