blob: 9c822df7292156102fc8fa47d793f2232e1e2d80 [file] [log] [blame]
Andrew Geisslere4960ee2020-03-30 14:31:52 -05001#include "config.h"
2
3#include "elog_entry.hpp"
4#include "log_manager.hpp"
Patrick Williamsfa2d9622024-09-30 16:25:43 -04005#include "paths.hpp"
Andrew Geisslere4960ee2020-03-30 14:31:52 -05006
7#include <sdbusplus/bus.hpp>
8#include <sdbusplus/test/sdbus_mock.hpp>
9
Patrick Williams2544b412022-10-04 08:41:06 -050010#include <filesystem>
11
Andrew Geisslere4960ee2020-03-30 14:31:52 -050012#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
15namespace phosphor
16{
17namespace logging
18{
19namespace test
20{
21
22class TestQuiesceOnError : public testing::Test
23{
24 public:
25 sdbusplus::SdBusMock sdbusMock;
Patrick Williams45e83522022-07-22 19:26:52 -050026 sdbusplus::bus_t mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
Andrew Geisslere4960ee2020-03-30 14:31:52 -050027 phosphor::logging::internal::Manager manager;
28
29 TestQuiesceOnError() : manager(mockedBus, OBJ_INTERNAL)
30 {
Andrew Geisslerce9fe692020-06-16 14:23:10 -050031 // Ensure any errors serializing to filesystem have directory created
Patrick Williamsfa2d9622024-09-30 16:25:43 -040032 std::filesystem::create_directories(paths::error());
Andrew Geisslere4960ee2020-03-30 14:31:52 -050033 }
34};
35
36// Test that false is returned when no callout is present in the log
37TEST_F(TestQuiesceOnError, testNoCallout)
38{
39 uint32_t id = 99;
40 uint64_t timestamp{100};
41 std::string message{"test error"};
42 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -060043 std::string path{"/tmp/99"};
Patrick Williamsea21d992024-11-22 17:06:35 -050044 std::map<std::string, std::string> testData{{"no", "no"},
45 {"callout", "callout"}};
Andrew Geisslere4960ee2020-03-30 14:31:52 -050046 phosphor::logging::AssociationList associations{};
47
48 Entry elog{mockedBus,
49 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
50 id,
51 timestamp,
52 Entry::Level::Informational,
53 std::move(message),
54 std::move(testData),
55 std::move(associations),
56 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -060057 path,
Andrew Geisslere4960ee2020-03-30 14:31:52 -050058 manager};
59
60 EXPECT_EQ(manager.isCalloutPresent(elog), false);
61}
62
63// Test that trues is returned when a callout is present in the log
64TEST_F(TestQuiesceOnError, testCallout)
65{
66 uint32_t id = 99;
67 uint64_t timestamp{100};
68 std::string message{"test error"};
69 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -060070 std::string path{"/tmp/99"};
Patrick Williamsea21d992024-11-22 17:06:35 -050071 std::map<std::string, std::string> testData{
72 {"CALLOUT_INVENTORY_PATH",
73 "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
Andrew Geisslere4960ee2020-03-30 14:31:52 -050074 phosphor::logging::AssociationList associations{};
75
76 Entry elog{mockedBus,
77 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
78 id,
79 timestamp,
80 Entry::Level::Informational,
81 std::move(message),
82 std::move(testData),
83 std::move(associations),
84 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -060085 path,
Andrew Geisslere4960ee2020-03-30 14:31:52 -050086 manager};
87
88 EXPECT_EQ(manager.isCalloutPresent(elog), true);
89}
90
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -050091// Test that a blocking error is created on entry with callout
92TEST_F(TestQuiesceOnError, testBlockingErrorsCreated)
93{
94 uint32_t id = 100;
95 uint64_t timestamp{100};
96 std::string message{"test error"};
97 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -060098 std::string path{"/tmp/99"};
Patrick Williamsea21d992024-11-22 17:06:35 -050099 std::map<std::string, std::string> testData{
100 {"CALLOUT_INVENTORY_PATH",
101 "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500102 phosphor::logging::AssociationList associations{};
103
104 // Ensure D-Bus object created for this blocking error
105 // First allow any number of sd_bus_emit_object_added calls
106 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
107 .Times(testing::AnyNumber());
108 // Second verify the new block100 object is created once
109 EXPECT_CALL(sdbusMock,
110 sd_bus_emit_object_added(
111 testing::_, testing::HasSubstr(
112 "/xyz/openbmc_project/logging/block100")))
113 .Times(1);
114
115 Entry elog{mockedBus,
116 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
117 id,
118 timestamp,
119 Entry::Level::Informational,
120 std::move(message),
121 std::move(testData),
122 std::move(associations),
123 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -0600124 path,
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500125 manager};
126
Andrew Geissler32874542020-07-09 09:17:03 -0500127 manager.quiesceOnError(id);
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500128 // Created error with callout so expect a blocking error now
129 EXPECT_EQ(manager.getBlockingErrSize(), 1);
Andrew Geisslerced6e2a2020-04-07 16:15:29 -0500130
131 // Now delete the error and make sure the object and entry go away
132 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
133 .Times(testing::AnyNumber());
134 EXPECT_CALL(sdbusMock,
135 sd_bus_emit_object_removed(
136 testing::_, testing::HasSubstr(
137 "/xyz/openbmc_project/logging/block100")))
138 .Times(1);
139
140 // Make sure nothing happens within invalid id
141 manager.checkAndRemoveBlockingError(id + 1);
142 EXPECT_EQ(manager.getBlockingErrSize(), 1);
143
144 manager.checkAndRemoveBlockingError(id);
145 EXPECT_EQ(manager.getBlockingErrSize(), 0);
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500146}
147
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500148// Test that a blocking error is created on entry with callout
149TEST_F(TestQuiesceOnError, testBlockingErrorsResolved)
150{
151 uint32_t id = 101;
152 uint64_t timestamp{100};
153 std::string message{"test error"};
154 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -0600155 std::string path{"/tmp/99"};
Patrick Williamsea21d992024-11-22 17:06:35 -0500156 std::map<std::string, std::string> testData{
157 {"CALLOUT_INVENTORY_PATH",
158 "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500159 phosphor::logging::AssociationList associations{};
160
161 // Ensure D-Bus object created for this blocking error
162 // First allow any number of sd_bus_emit_object_added calls
163 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
164 .Times(testing::AnyNumber());
165 // Second verify the new block100 object is created once
166 EXPECT_CALL(sdbusMock,
167 sd_bus_emit_object_added(
168 testing::_, testing::HasSubstr(
169 "/xyz/openbmc_project/logging/block101")))
170 .Times(1);
171
172 Entry elog{mockedBus,
173 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
174 id,
175 timestamp,
176 Entry::Level::Informational,
177 std::move(message),
178 std::move(testData),
179 std::move(associations),
180 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -0600181 path,
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500182 manager};
183
Andrew Geissler32874542020-07-09 09:17:03 -0500184 manager.quiesceOnError(id);
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500185 // Created error with callout so expect a blocking error now
186 EXPECT_EQ(manager.getBlockingErrSize(), 1);
187 // Also should have a callback create looking for entry to be resolved
188 EXPECT_EQ(manager.getEntryCallbackSize(), 1);
189
190 // Now resolve the error and make sure the object and entry go away
191 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
192 .Times(testing::AnyNumber());
193 EXPECT_CALL(sdbusMock,
194 sd_bus_emit_object_removed(
195 testing::_, testing::HasSubstr(
196 "/xyz/openbmc_project/logging/block101")))
197 .Times(1);
198
199 elog.resolved(true);
200 // Note that property signal callbacks do not work in unit test so directly
201 // call the interface to find and resolve blocking entries
202 manager.checkAndRemoveBlockingError(101);
203 EXPECT_EQ(manager.getBlockingErrSize(), 0);
204 EXPECT_EQ(manager.getEntryCallbackSize(), 0);
205}
206
Andrew Geissler72a1cca2020-09-10 16:49:09 -0500207// Test that a blocking error is only created once for an individual bmc id
208TEST_F(TestQuiesceOnError, testBlockingErrorTwice)
209{
210 uint32_t id = 100;
211 uint64_t timestamp{100};
212 std::string message{"test error"};
213 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -0600214 std::string path{"/tmp/99"};
Patrick Williamsea21d992024-11-22 17:06:35 -0500215 std::map<std::string, std::string> testData{
216 {"CALLOUT_INVENTORY_PATH",
217 "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
Andrew Geissler72a1cca2020-09-10 16:49:09 -0500218 phosphor::logging::AssociationList associations{};
219
220 // Ensure D-Bus object created for this blocking error
221 // First allow any number of sd_bus_emit_object_added calls
222 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
223 .Times(testing::AnyNumber());
224 // Second verify the new block100 object is created once
225 EXPECT_CALL(sdbusMock,
226 sd_bus_emit_object_added(
227 testing::_, testing::HasSubstr(
228 "/xyz/openbmc_project/logging/block100")))
229 .Times(1);
230
231 Entry elog{mockedBus,
232 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
233 id,
234 timestamp,
235 Entry::Level::Informational,
236 std::move(message),
237 std::move(testData),
238 std::move(associations),
239 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -0600240 path,
Andrew Geissler72a1cca2020-09-10 16:49:09 -0500241 manager};
242
243 manager.quiesceOnError(id);
244 // Created error with callout so expect a blocking error now
245 EXPECT_EQ(manager.getBlockingErrSize(), 1);
246
247 // Now pass in same ID and make sure it's ignored
248 manager.quiesceOnError(id);
249
250 // Now delete the error and make sure the object and entry go away
251 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
252 .Times(testing::AnyNumber());
253 EXPECT_CALL(sdbusMock,
254 sd_bus_emit_object_removed(
255 testing::_, testing::HasSubstr(
256 "/xyz/openbmc_project/logging/block100")))
257 .Times(1);
258
259 manager.checkAndRemoveBlockingError(id);
260 EXPECT_EQ(manager.getBlockingErrSize(), 0);
261}
262
Andrew Geisslere4960ee2020-03-30 14:31:52 -0500263} // namespace test
264} // namespace logging
265} // namespace phosphor