xref: /openbmc/phosphor-logging/test/elog_quiesce_test.cpp (revision ea21d995389412b4cea411f647176641b5cf0a9a)
1e4960ee7SAndrew Geissler #include "config.h"
2e4960ee7SAndrew Geissler 
3e4960ee7SAndrew Geissler #include "elog_entry.hpp"
4e4960ee7SAndrew Geissler #include "log_manager.hpp"
5fa2d962bSPatrick Williams #include "paths.hpp"
6e4960ee7SAndrew Geissler 
7e4960ee7SAndrew Geissler #include <sdbusplus/bus.hpp>
8e4960ee7SAndrew Geissler #include <sdbusplus/test/sdbus_mock.hpp>
9e4960ee7SAndrew Geissler 
102544b419SPatrick Williams #include <filesystem>
112544b419SPatrick Williams 
12e4960ee7SAndrew Geissler #include <gmock/gmock.h>
13e4960ee7SAndrew Geissler #include <gtest/gtest.h>
14e4960ee7SAndrew Geissler 
15e4960ee7SAndrew Geissler namespace phosphor
16e4960ee7SAndrew Geissler {
17e4960ee7SAndrew Geissler namespace logging
18e4960ee7SAndrew Geissler {
19e4960ee7SAndrew Geissler namespace test
20e4960ee7SAndrew Geissler {
21e4960ee7SAndrew Geissler 
22e4960ee7SAndrew Geissler class TestQuiesceOnError : public testing::Test
23e4960ee7SAndrew Geissler {
24e4960ee7SAndrew Geissler   public:
25e4960ee7SAndrew Geissler     sdbusplus::SdBusMock sdbusMock;
2645e83521SPatrick Williams     sdbusplus::bus_t mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
27e4960ee7SAndrew Geissler     phosphor::logging::internal::Manager manager;
28e4960ee7SAndrew Geissler 
TestQuiesceOnError()29e4960ee7SAndrew Geissler     TestQuiesceOnError() : manager(mockedBus, OBJ_INTERNAL)
30e4960ee7SAndrew Geissler     {
31ce9fe693SAndrew Geissler         // Ensure any errors serializing to filesystem have directory created
32fa2d962bSPatrick Williams         std::filesystem::create_directories(paths::error());
33e4960ee7SAndrew Geissler     }
34e4960ee7SAndrew Geissler };
35e4960ee7SAndrew Geissler 
36e4960ee7SAndrew Geissler // Test that false is returned when no callout is present in the log
TEST_F(TestQuiesceOnError,testNoCallout)37e4960ee7SAndrew Geissler TEST_F(TestQuiesceOnError, testNoCallout)
38e4960ee7SAndrew Geissler {
39e4960ee7SAndrew Geissler     uint32_t id = 99;
40e4960ee7SAndrew Geissler     uint64_t timestamp{100};
41e4960ee7SAndrew Geissler     std::string message{"test error"};
42e4960ee7SAndrew Geissler     std::string fwLevel{"level42"};
43fb978da4SMatt Spinler     std::string path{"/tmp/99"};
44*ea21d995SPatrick Williams     std::map<std::string, std::string> testData{{"no", "no"},
45*ea21d995SPatrick Williams                                                 {"callout", "callout"}};
46e4960ee7SAndrew Geissler     phosphor::logging::AssociationList associations{};
47e4960ee7SAndrew Geissler 
48e4960ee7SAndrew Geissler     Entry elog{mockedBus,
49e4960ee7SAndrew Geissler                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
50e4960ee7SAndrew Geissler                id,
51e4960ee7SAndrew Geissler                timestamp,
52e4960ee7SAndrew Geissler                Entry::Level::Informational,
53e4960ee7SAndrew Geissler                std::move(message),
54e4960ee7SAndrew Geissler                std::move(testData),
55e4960ee7SAndrew Geissler                std::move(associations),
56e4960ee7SAndrew Geissler                fwLevel,
57fb978da4SMatt Spinler                path,
58e4960ee7SAndrew Geissler                manager};
59e4960ee7SAndrew Geissler 
60e4960ee7SAndrew Geissler     EXPECT_EQ(manager.isCalloutPresent(elog), false);
61e4960ee7SAndrew Geissler }
62e4960ee7SAndrew Geissler 
63e4960ee7SAndrew Geissler // Test that trues is returned when a callout is present in the log
TEST_F(TestQuiesceOnError,testCallout)64e4960ee7SAndrew Geissler TEST_F(TestQuiesceOnError, testCallout)
65e4960ee7SAndrew Geissler {
66e4960ee7SAndrew Geissler     uint32_t id = 99;
67e4960ee7SAndrew Geissler     uint64_t timestamp{100};
68e4960ee7SAndrew Geissler     std::string message{"test error"};
69e4960ee7SAndrew Geissler     std::string fwLevel{"level42"};
70fb978da4SMatt Spinler     std::string path{"/tmp/99"};
71*ea21d995SPatrick Williams     std::map<std::string, std::string> testData{
72*ea21d995SPatrick Williams         {"CALLOUT_INVENTORY_PATH",
73*ea21d995SPatrick Williams          "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
74e4960ee7SAndrew Geissler     phosphor::logging::AssociationList associations{};
75e4960ee7SAndrew Geissler 
76e4960ee7SAndrew Geissler     Entry elog{mockedBus,
77e4960ee7SAndrew Geissler                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
78e4960ee7SAndrew Geissler                id,
79e4960ee7SAndrew Geissler                timestamp,
80e4960ee7SAndrew Geissler                Entry::Level::Informational,
81e4960ee7SAndrew Geissler                std::move(message),
82e4960ee7SAndrew Geissler                std::move(testData),
83e4960ee7SAndrew Geissler                std::move(associations),
84e4960ee7SAndrew Geissler                fwLevel,
85fb978da4SMatt Spinler                path,
86e4960ee7SAndrew Geissler                manager};
87e4960ee7SAndrew Geissler 
88e4960ee7SAndrew Geissler     EXPECT_EQ(manager.isCalloutPresent(elog), true);
89e4960ee7SAndrew Geissler }
90e4960ee7SAndrew Geissler 
916a0ef6f5SAndrew Geissler // Test that a blocking error is created on entry with callout
TEST_F(TestQuiesceOnError,testBlockingErrorsCreated)926a0ef6f5SAndrew Geissler TEST_F(TestQuiesceOnError, testBlockingErrorsCreated)
936a0ef6f5SAndrew Geissler {
946a0ef6f5SAndrew Geissler     uint32_t id = 100;
956a0ef6f5SAndrew Geissler     uint64_t timestamp{100};
966a0ef6f5SAndrew Geissler     std::string message{"test error"};
976a0ef6f5SAndrew Geissler     std::string fwLevel{"level42"};
98fb978da4SMatt Spinler     std::string path{"/tmp/99"};
99*ea21d995SPatrick Williams     std::map<std::string, std::string> testData{
100*ea21d995SPatrick Williams         {"CALLOUT_INVENTORY_PATH",
101*ea21d995SPatrick Williams          "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
1026a0ef6f5SAndrew Geissler     phosphor::logging::AssociationList associations{};
1036a0ef6f5SAndrew Geissler 
1046a0ef6f5SAndrew Geissler     // Ensure D-Bus object created for this blocking error
1056a0ef6f5SAndrew Geissler     // First allow any number of sd_bus_emit_object_added calls
1066a0ef6f5SAndrew Geissler     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
1076a0ef6f5SAndrew Geissler         .Times(testing::AnyNumber());
1086a0ef6f5SAndrew Geissler     // Second verify the new block100 object is created once
1096a0ef6f5SAndrew Geissler     EXPECT_CALL(sdbusMock,
1106a0ef6f5SAndrew Geissler                 sd_bus_emit_object_added(
1116a0ef6f5SAndrew Geissler                     testing::_, testing::HasSubstr(
1126a0ef6f5SAndrew Geissler                                     "/xyz/openbmc_project/logging/block100")))
1136a0ef6f5SAndrew Geissler         .Times(1);
1146a0ef6f5SAndrew Geissler 
1156a0ef6f5SAndrew Geissler     Entry elog{mockedBus,
1166a0ef6f5SAndrew Geissler                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
1176a0ef6f5SAndrew Geissler                id,
1186a0ef6f5SAndrew Geissler                timestamp,
1196a0ef6f5SAndrew Geissler                Entry::Level::Informational,
1206a0ef6f5SAndrew Geissler                std::move(message),
1216a0ef6f5SAndrew Geissler                std::move(testData),
1226a0ef6f5SAndrew Geissler                std::move(associations),
1236a0ef6f5SAndrew Geissler                fwLevel,
124fb978da4SMatt Spinler                path,
1256a0ef6f5SAndrew Geissler                manager};
1266a0ef6f5SAndrew Geissler 
12732874543SAndrew Geissler     manager.quiesceOnError(id);
1286a0ef6f5SAndrew Geissler     // Created error with callout so expect a blocking error now
1296a0ef6f5SAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 1);
130ced6e2a0SAndrew Geissler 
131ced6e2a0SAndrew Geissler     // Now delete the error and make sure the object and entry go away
132ced6e2a0SAndrew Geissler     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
133ced6e2a0SAndrew Geissler         .Times(testing::AnyNumber());
134ced6e2a0SAndrew Geissler     EXPECT_CALL(sdbusMock,
135ced6e2a0SAndrew Geissler                 sd_bus_emit_object_removed(
136ced6e2a0SAndrew Geissler                     testing::_, testing::HasSubstr(
137ced6e2a0SAndrew Geissler                                     "/xyz/openbmc_project/logging/block100")))
138ced6e2a0SAndrew Geissler         .Times(1);
139ced6e2a0SAndrew Geissler 
140ced6e2a0SAndrew Geissler     // Make sure nothing happens within invalid id
141ced6e2a0SAndrew Geissler     manager.checkAndRemoveBlockingError(id + 1);
142ced6e2a0SAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 1);
143ced6e2a0SAndrew Geissler 
144ced6e2a0SAndrew Geissler     manager.checkAndRemoveBlockingError(id);
145ced6e2a0SAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 0);
1466a0ef6f5SAndrew Geissler }
1476a0ef6f5SAndrew Geissler 
1487f6d4bcfSAndrew Geissler // Test that a blocking error is created on entry with callout
TEST_F(TestQuiesceOnError,testBlockingErrorsResolved)1497f6d4bcfSAndrew Geissler TEST_F(TestQuiesceOnError, testBlockingErrorsResolved)
1507f6d4bcfSAndrew Geissler {
1517f6d4bcfSAndrew Geissler     uint32_t id = 101;
1527f6d4bcfSAndrew Geissler     uint64_t timestamp{100};
1537f6d4bcfSAndrew Geissler     std::string message{"test error"};
1547f6d4bcfSAndrew Geissler     std::string fwLevel{"level42"};
155fb978da4SMatt Spinler     std::string path{"/tmp/99"};
156*ea21d995SPatrick Williams     std::map<std::string, std::string> testData{
157*ea21d995SPatrick Williams         {"CALLOUT_INVENTORY_PATH",
158*ea21d995SPatrick Williams          "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
1597f6d4bcfSAndrew Geissler     phosphor::logging::AssociationList associations{};
1607f6d4bcfSAndrew Geissler 
1617f6d4bcfSAndrew Geissler     // Ensure D-Bus object created for this blocking error
1627f6d4bcfSAndrew Geissler     // First allow any number of sd_bus_emit_object_added calls
1637f6d4bcfSAndrew Geissler     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
1647f6d4bcfSAndrew Geissler         .Times(testing::AnyNumber());
1657f6d4bcfSAndrew Geissler     // Second verify the new block100 object is created once
1667f6d4bcfSAndrew Geissler     EXPECT_CALL(sdbusMock,
1677f6d4bcfSAndrew Geissler                 sd_bus_emit_object_added(
1687f6d4bcfSAndrew Geissler                     testing::_, testing::HasSubstr(
1697f6d4bcfSAndrew Geissler                                     "/xyz/openbmc_project/logging/block101")))
1707f6d4bcfSAndrew Geissler         .Times(1);
1717f6d4bcfSAndrew Geissler 
1727f6d4bcfSAndrew Geissler     Entry elog{mockedBus,
1737f6d4bcfSAndrew Geissler                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
1747f6d4bcfSAndrew Geissler                id,
1757f6d4bcfSAndrew Geissler                timestamp,
1767f6d4bcfSAndrew Geissler                Entry::Level::Informational,
1777f6d4bcfSAndrew Geissler                std::move(message),
1787f6d4bcfSAndrew Geissler                std::move(testData),
1797f6d4bcfSAndrew Geissler                std::move(associations),
1807f6d4bcfSAndrew Geissler                fwLevel,
181fb978da4SMatt Spinler                path,
1827f6d4bcfSAndrew Geissler                manager};
1837f6d4bcfSAndrew Geissler 
18432874543SAndrew Geissler     manager.quiesceOnError(id);
1857f6d4bcfSAndrew Geissler     // Created error with callout so expect a blocking error now
1867f6d4bcfSAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 1);
1877f6d4bcfSAndrew Geissler     // Also should have a callback create looking for entry to be resolved
1887f6d4bcfSAndrew Geissler     EXPECT_EQ(manager.getEntryCallbackSize(), 1);
1897f6d4bcfSAndrew Geissler 
1907f6d4bcfSAndrew Geissler     // Now resolve the error and make sure the object and entry go away
1917f6d4bcfSAndrew Geissler     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
1927f6d4bcfSAndrew Geissler         .Times(testing::AnyNumber());
1937f6d4bcfSAndrew Geissler     EXPECT_CALL(sdbusMock,
1947f6d4bcfSAndrew Geissler                 sd_bus_emit_object_removed(
1957f6d4bcfSAndrew Geissler                     testing::_, testing::HasSubstr(
1967f6d4bcfSAndrew Geissler                                     "/xyz/openbmc_project/logging/block101")))
1977f6d4bcfSAndrew Geissler         .Times(1);
1987f6d4bcfSAndrew Geissler 
1997f6d4bcfSAndrew Geissler     elog.resolved(true);
2007f6d4bcfSAndrew Geissler     // Note that property signal callbacks do not work in unit test so directly
2017f6d4bcfSAndrew Geissler     // call the interface to find and resolve blocking entries
2027f6d4bcfSAndrew Geissler     manager.checkAndRemoveBlockingError(101);
2037f6d4bcfSAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 0);
2047f6d4bcfSAndrew Geissler     EXPECT_EQ(manager.getEntryCallbackSize(), 0);
2057f6d4bcfSAndrew Geissler }
2067f6d4bcfSAndrew Geissler 
20772a1cca2SAndrew Geissler // Test that a blocking error is only created once for an individual bmc id
TEST_F(TestQuiesceOnError,testBlockingErrorTwice)20872a1cca2SAndrew Geissler TEST_F(TestQuiesceOnError, testBlockingErrorTwice)
20972a1cca2SAndrew Geissler {
21072a1cca2SAndrew Geissler     uint32_t id = 100;
21172a1cca2SAndrew Geissler     uint64_t timestamp{100};
21272a1cca2SAndrew Geissler     std::string message{"test error"};
21372a1cca2SAndrew Geissler     std::string fwLevel{"level42"};
214fb978da4SMatt Spinler     std::string path{"/tmp/99"};
215*ea21d995SPatrick Williams     std::map<std::string, std::string> testData{
216*ea21d995SPatrick Williams         {"CALLOUT_INVENTORY_PATH",
217*ea21d995SPatrick Williams          "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0/"}};
21872a1cca2SAndrew Geissler     phosphor::logging::AssociationList associations{};
21972a1cca2SAndrew Geissler 
22072a1cca2SAndrew Geissler     // Ensure D-Bus object created for this blocking error
22172a1cca2SAndrew Geissler     // First allow any number of sd_bus_emit_object_added calls
22272a1cca2SAndrew Geissler     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
22372a1cca2SAndrew Geissler         .Times(testing::AnyNumber());
22472a1cca2SAndrew Geissler     // Second verify the new block100 object is created once
22572a1cca2SAndrew Geissler     EXPECT_CALL(sdbusMock,
22672a1cca2SAndrew Geissler                 sd_bus_emit_object_added(
22772a1cca2SAndrew Geissler                     testing::_, testing::HasSubstr(
22872a1cca2SAndrew Geissler                                     "/xyz/openbmc_project/logging/block100")))
22972a1cca2SAndrew Geissler         .Times(1);
23072a1cca2SAndrew Geissler 
23172a1cca2SAndrew Geissler     Entry elog{mockedBus,
23272a1cca2SAndrew Geissler                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
23372a1cca2SAndrew Geissler                id,
23472a1cca2SAndrew Geissler                timestamp,
23572a1cca2SAndrew Geissler                Entry::Level::Informational,
23672a1cca2SAndrew Geissler                std::move(message),
23772a1cca2SAndrew Geissler                std::move(testData),
23872a1cca2SAndrew Geissler                std::move(associations),
23972a1cca2SAndrew Geissler                fwLevel,
240fb978da4SMatt Spinler                path,
24172a1cca2SAndrew Geissler                manager};
24272a1cca2SAndrew Geissler 
24372a1cca2SAndrew Geissler     manager.quiesceOnError(id);
24472a1cca2SAndrew Geissler     // Created error with callout so expect a blocking error now
24572a1cca2SAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 1);
24672a1cca2SAndrew Geissler 
24772a1cca2SAndrew Geissler     // Now pass in same ID and make sure it's ignored
24872a1cca2SAndrew Geissler     manager.quiesceOnError(id);
24972a1cca2SAndrew Geissler 
25072a1cca2SAndrew Geissler     // Now delete the error and make sure the object and entry go away
25172a1cca2SAndrew Geissler     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
25272a1cca2SAndrew Geissler         .Times(testing::AnyNumber());
25372a1cca2SAndrew Geissler     EXPECT_CALL(sdbusMock,
25472a1cca2SAndrew Geissler                 sd_bus_emit_object_removed(
25572a1cca2SAndrew Geissler                     testing::_, testing::HasSubstr(
25672a1cca2SAndrew Geissler                                     "/xyz/openbmc_project/logging/block100")))
25772a1cca2SAndrew Geissler         .Times(1);
25872a1cca2SAndrew Geissler 
25972a1cca2SAndrew Geissler     manager.checkAndRemoveBlockingError(id);
26072a1cca2SAndrew Geissler     EXPECT_EQ(manager.getBlockingErrSize(), 0);
26172a1cca2SAndrew Geissler }
26272a1cca2SAndrew Geissler 
263e4960ee7SAndrew Geissler } // namespace test
264e4960ee7SAndrew Geissler } // namespace logging
265e4960ee7SAndrew Geissler } // namespace phosphor
266