xref: /openbmc/phosphor-logging/test/elog_quiesce_test.cpp (revision 7f6d4bcfd5c467eb21e7e064c3d9a156c4b67e5d)
1 #include "config.h"
2 
3 #include "elog_entry.hpp"
4 #include "log_manager.hpp"
5 
6 #include <sdbusplus/bus.hpp>
7 #include <sdbusplus/test/sdbus_mock.hpp>
8 
9 #include <gmock/gmock.h>
10 #include <gtest/gtest.h>
11 
12 namespace phosphor
13 {
14 namespace logging
15 {
16 namespace test
17 {
18 
19 class TestQuiesceOnError : public testing::Test
20 {
21   public:
22     sdbusplus::SdBusMock sdbusMock;
23     sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
24     phosphor::logging::internal::Manager manager;
25 
26     TestQuiesceOnError() : manager(mockedBus, OBJ_INTERNAL)
27     {
28     }
29 };
30 
31 // Test that false is returned when no callout is present in the log
32 TEST_F(TestQuiesceOnError, testNoCallout)
33 {
34     uint32_t id = 99;
35     uint64_t timestamp{100};
36     std::string message{"test error"};
37     std::string fwLevel{"level42"};
38     std::vector<std::string> testData{"no", "callout"};
39     phosphor::logging::AssociationList associations{};
40 
41     Entry elog{mockedBus,
42                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
43                id,
44                timestamp,
45                Entry::Level::Informational,
46                std::move(message),
47                std::move(testData),
48                std::move(associations),
49                fwLevel,
50                manager};
51 
52     EXPECT_EQ(manager.isCalloutPresent(elog), false);
53 }
54 
55 // Test that trues is returned when a callout is present in the log
56 TEST_F(TestQuiesceOnError, testCallout)
57 {
58     uint32_t id = 99;
59     uint64_t timestamp{100};
60     std::string message{"test error"};
61     std::string fwLevel{"level42"};
62     std::vector<std::string> testData{
63         "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
64         "motherboard/powersupply0/"};
65     phosphor::logging::AssociationList associations{};
66 
67     Entry elog{mockedBus,
68                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
69                id,
70                timestamp,
71                Entry::Level::Informational,
72                std::move(message),
73                std::move(testData),
74                std::move(associations),
75                fwLevel,
76                manager};
77 
78     EXPECT_EQ(manager.isCalloutPresent(elog), true);
79 }
80 
81 // Test that no blocking errors are created when no callout
82 TEST_F(TestQuiesceOnError, testNoBlockingErrorsCreated)
83 {
84     uint32_t id = 99;
85     uint64_t timestamp{100};
86     std::string message{"test error"};
87     std::string fwLevel{"level42"};
88     std::vector<std::string> testData{"no", "callout"};
89     phosphor::logging::AssociationList associations{};
90 
91     Entry elog{mockedBus,
92                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
93                id,
94                timestamp,
95                Entry::Level::Informational,
96                std::move(message),
97                std::move(testData),
98                std::move(associations),
99                fwLevel,
100                manager};
101 
102     manager.checkQuiesceOnError(elog);
103     EXPECT_EQ(manager.getBlockingErrSize(), 0);
104 }
105 
106 // Test that a blocking error is created on entry with callout
107 TEST_F(TestQuiesceOnError, testBlockingErrorsCreated)
108 {
109     uint32_t id = 100;
110     uint64_t timestamp{100};
111     std::string message{"test error"};
112     std::string fwLevel{"level42"};
113     std::vector<std::string> testData{
114         "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
115         "motherboard/powersupply0/"};
116     phosphor::logging::AssociationList associations{};
117 
118     // Ensure D-Bus object created for this blocking error
119     // First allow any number of sd_bus_emit_object_added calls
120     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
121         .Times(testing::AnyNumber());
122     // Second verify the new block100 object is created once
123     EXPECT_CALL(sdbusMock,
124                 sd_bus_emit_object_added(
125                     testing::_, testing::HasSubstr(
126                                     "/xyz/openbmc_project/logging/block100")))
127         .Times(1);
128 
129     Entry elog{mockedBus,
130                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
131                id,
132                timestamp,
133                Entry::Level::Informational,
134                std::move(message),
135                std::move(testData),
136                std::move(associations),
137                fwLevel,
138                manager};
139 
140     manager.checkQuiesceOnError(elog);
141     // Created error with callout so expect a blocking error now
142     EXPECT_EQ(manager.getBlockingErrSize(), 1);
143 
144     // Now delete the error and make sure the object and entry go away
145     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
146         .Times(testing::AnyNumber());
147     EXPECT_CALL(sdbusMock,
148                 sd_bus_emit_object_removed(
149                     testing::_, testing::HasSubstr(
150                                     "/xyz/openbmc_project/logging/block100")))
151         .Times(1);
152 
153     // Make sure nothing happens within invalid id
154     manager.checkAndRemoveBlockingError(id + 1);
155     EXPECT_EQ(manager.getBlockingErrSize(), 1);
156 
157     manager.checkAndRemoveBlockingError(id);
158     EXPECT_EQ(manager.getBlockingErrSize(), 0);
159 }
160 
161 // Test that a blocking error is created on entry with callout
162 TEST_F(TestQuiesceOnError, testBlockingErrorsResolved)
163 {
164     uint32_t id = 101;
165     uint64_t timestamp{100};
166     std::string message{"test error"};
167     std::string fwLevel{"level42"};
168     std::vector<std::string> testData{
169         "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
170         "motherboard/powersupply0/"};
171     phosphor::logging::AssociationList associations{};
172 
173     // Ensure D-Bus object created for this blocking error
174     // First allow any number of sd_bus_emit_object_added calls
175     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
176         .Times(testing::AnyNumber());
177     // Second verify the new block100 object is created once
178     EXPECT_CALL(sdbusMock,
179                 sd_bus_emit_object_added(
180                     testing::_, testing::HasSubstr(
181                                     "/xyz/openbmc_project/logging/block101")))
182         .Times(1);
183 
184     Entry elog{mockedBus,
185                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
186                id,
187                timestamp,
188                Entry::Level::Informational,
189                std::move(message),
190                std::move(testData),
191                std::move(associations),
192                fwLevel,
193                manager};
194 
195     manager.checkQuiesceOnError(elog);
196     // Created error with callout so expect a blocking error now
197     EXPECT_EQ(manager.getBlockingErrSize(), 1);
198     // Also should have a callback create looking for entry to be resolved
199     EXPECT_EQ(manager.getEntryCallbackSize(), 1);
200 
201     // Now resolve the error and make sure the object and entry go away
202     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(testing::_, testing::_))
203         .Times(testing::AnyNumber());
204     EXPECT_CALL(sdbusMock,
205                 sd_bus_emit_object_removed(
206                     testing::_, testing::HasSubstr(
207                                     "/xyz/openbmc_project/logging/block101")))
208         .Times(1);
209 
210     elog.resolved(true);
211     // Note that property signal callbacks do not work in unit test so directly
212     // call the interface to find and resolve blocking entries
213     manager.checkAndRemoveBlockingError(101);
214     EXPECT_EQ(manager.getBlockingErrSize(), 0);
215     EXPECT_EQ(manager.getEntryCallbackSize(), 0);
216 }
217 
218 } // namespace test
219 } // namespace logging
220 } // namespace phosphor
221