blob: 7894f95914704fed0d0d4618fafdf508cfe5963e [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"};
Andrew Geisslere4960ee2020-03-30 14:31:52 -050044 std::vector<std::string> testData{"no", "callout"};
45 phosphor::logging::AssociationList associations{};
46
47 Entry elog{mockedBus,
48 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
49 id,
50 timestamp,
51 Entry::Level::Informational,
52 std::move(message),
53 std::move(testData),
54 std::move(associations),
55 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -060056 path,
Andrew Geisslere4960ee2020-03-30 14:31:52 -050057 manager};
58
59 EXPECT_EQ(manager.isCalloutPresent(elog), false);
60}
61
62// Test that trues is returned when a callout is present in the log
63TEST_F(TestQuiesceOnError, testCallout)
64{
65 uint32_t id = 99;
66 uint64_t timestamp{100};
67 std::string message{"test error"};
68 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -060069 std::string path{"/tmp/99"};
Andrew Geisslere4960ee2020-03-30 14:31:52 -050070 std::vector<std::string> testData{
71 "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
72 "motherboard/powersupply0/"};
73 phosphor::logging::AssociationList associations{};
74
75 Entry elog{mockedBus,
76 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
77 id,
78 timestamp,
79 Entry::Level::Informational,
80 std::move(message),
81 std::move(testData),
82 std::move(associations),
83 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -060084 path,
Andrew Geisslere4960ee2020-03-30 14:31:52 -050085 manager};
86
87 EXPECT_EQ(manager.isCalloutPresent(elog), true);
88}
89
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -050090// Test that a blocking error is created on entry with callout
91TEST_F(TestQuiesceOnError, testBlockingErrorsCreated)
92{
93 uint32_t id = 100;
94 uint64_t timestamp{100};
95 std::string message{"test error"};
96 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -060097 std::string path{"/tmp/99"};
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -050098 std::vector<std::string> testData{
99 "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
100 "motherboard/powersupply0/"};
101 phosphor::logging::AssociationList associations{};
102
103 // Ensure D-Bus object created for this blocking error
104 // First allow any number of sd_bus_emit_object_added calls
105 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
106 .Times(testing::AnyNumber());
107 // Second verify the new block100 object is created once
108 EXPECT_CALL(sdbusMock,
109 sd_bus_emit_object_added(
110 testing::_, testing::HasSubstr(
111 "/xyz/openbmc_project/logging/block100")))
112 .Times(1);
113
114 Entry elog{mockedBus,
115 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
116 id,
117 timestamp,
118 Entry::Level::Informational,
119 std::move(message),
120 std::move(testData),
121 std::move(associations),
122 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -0600123 path,
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500124 manager};
125
Andrew Geissler32874542020-07-09 09:17:03 -0500126 manager.quiesceOnError(id);
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500127 // Created error with callout so expect a blocking error now
128 EXPECT_EQ(manager.getBlockingErrSize(), 1);
Andrew Geisslerced6e2a2020-04-07 16:15:29 -0500129
130 // Now delete the error and make sure the object and entry go away
131 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
132 .Times(testing::AnyNumber());
133 EXPECT_CALL(sdbusMock,
134 sd_bus_emit_object_removed(
135 testing::_, testing::HasSubstr(
136 "/xyz/openbmc_project/logging/block100")))
137 .Times(1);
138
139 // Make sure nothing happens within invalid id
140 manager.checkAndRemoveBlockingError(id + 1);
141 EXPECT_EQ(manager.getBlockingErrSize(), 1);
142
143 manager.checkAndRemoveBlockingError(id);
144 EXPECT_EQ(manager.getBlockingErrSize(), 0);
Andrew Geissler6a0ef6f2020-04-06 15:06:31 -0500145}
146
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500147// Test that a blocking error is created on entry with callout
148TEST_F(TestQuiesceOnError, testBlockingErrorsResolved)
149{
150 uint32_t id = 101;
151 uint64_t timestamp{100};
152 std::string message{"test error"};
153 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -0600154 std::string path{"/tmp/99"};
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500155 std::vector<std::string> testData{
156 "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
157 "motherboard/powersupply0/"};
158 phosphor::logging::AssociationList associations{};
159
160 // Ensure D-Bus object created for this blocking error
161 // First allow any number of sd_bus_emit_object_added calls
162 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
163 .Times(testing::AnyNumber());
164 // Second verify the new block100 object is created once
165 EXPECT_CALL(sdbusMock,
166 sd_bus_emit_object_added(
167 testing::_, testing::HasSubstr(
168 "/xyz/openbmc_project/logging/block101")))
169 .Times(1);
170
171 Entry elog{mockedBus,
172 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
173 id,
174 timestamp,
175 Entry::Level::Informational,
176 std::move(message),
177 std::move(testData),
178 std::move(associations),
179 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -0600180 path,
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500181 manager};
182
Andrew Geissler32874542020-07-09 09:17:03 -0500183 manager.quiesceOnError(id);
Andrew Geissler7f6d4bc2020-04-16 14:47:34 -0500184 // Created error with callout so expect a blocking error now
185 EXPECT_EQ(manager.getBlockingErrSize(), 1);
186 // Also should have a callback create looking for entry to be resolved
187 EXPECT_EQ(manager.getEntryCallbackSize(), 1);
188
189 // Now resolve the error and make sure the object and entry go away
190 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
191 .Times(testing::AnyNumber());
192 EXPECT_CALL(sdbusMock,
193 sd_bus_emit_object_removed(
194 testing::_, testing::HasSubstr(
195 "/xyz/openbmc_project/logging/block101")))
196 .Times(1);
197
198 elog.resolved(true);
199 // Note that property signal callbacks do not work in unit test so directly
200 // call the interface to find and resolve blocking entries
201 manager.checkAndRemoveBlockingError(101);
202 EXPECT_EQ(manager.getBlockingErrSize(), 0);
203 EXPECT_EQ(manager.getEntryCallbackSize(), 0);
204}
205
Andrew Geissler72a1cca2020-09-10 16:49:09 -0500206// Test that a blocking error is only created once for an individual bmc id
207TEST_F(TestQuiesceOnError, testBlockingErrorTwice)
208{
209 uint32_t id = 100;
210 uint64_t timestamp{100};
211 std::string message{"test error"};
212 std::string fwLevel{"level42"};
Matt Spinlerfb978da2022-01-21 08:42:24 -0600213 std::string path{"/tmp/99"};
Andrew Geissler72a1cca2020-09-10 16:49:09 -0500214 std::vector<std::string> testData{
215 "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
216 "motherboard/powersupply0/"};
217 phosphor::logging::AssociationList associations{};
218
219 // Ensure D-Bus object created for this blocking error
220 // First allow any number of sd_bus_emit_object_added calls
221 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
222 .Times(testing::AnyNumber());
223 // Second verify the new block100 object is created once
224 EXPECT_CALL(sdbusMock,
225 sd_bus_emit_object_added(
226 testing::_, testing::HasSubstr(
227 "/xyz/openbmc_project/logging/block100")))
228 .Times(1);
229
230 Entry elog{mockedBus,
231 std::string(OBJ_ENTRY) + '/' + std::to_string(id),
232 id,
233 timestamp,
234 Entry::Level::Informational,
235 std::move(message),
236 std::move(testData),
237 std::move(associations),
238 fwLevel,
Matt Spinlerfb978da2022-01-21 08:42:24 -0600239 path,
Andrew Geissler72a1cca2020-09-10 16:49:09 -0500240 manager};
241
242 manager.quiesceOnError(id);
243 // Created error with callout so expect a blocking error now
244 EXPECT_EQ(manager.getBlockingErrSize(), 1);
245
246 // Now pass in same ID and make sure it's ignored
247 manager.quiesceOnError(id);
248
249 // Now delete the error and make sure the object and entry go away
250 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
251 .Times(testing::AnyNumber());
252 EXPECT_CALL(sdbusMock,
253 sd_bus_emit_object_removed(
254 testing::_, testing::HasSubstr(
255 "/xyz/openbmc_project/logging/block100")))
256 .Times(1);
257
258 manager.checkAndRemoveBlockingError(id);
259 EXPECT_EQ(manager.getBlockingErrSize(), 0);
260}
261
Andrew Geisslere4960ee2020-03-30 14:31:52 -0500262} // namespace test
263} // namespace logging
264} // namespace phosphor