1 #include "config.h"
2 
3 #include "elog_entry.hpp"
4 #include "elog_serialize.hpp"
5 #include "extensions.hpp"
6 #include "log_manager.hpp"
7 #include "paths.hpp"
8 
9 #include <filesystem>
10 #include <thread>
11 
12 #include <gtest/gtest.h>
13 
14 namespace phosphor
15 {
16 namespace logging
17 {
18 namespace test
19 {
20 
21 using namespace std::chrono_literals;
22 namespace fs = std::filesystem;
23 
24 void deleteIsProhibitedMock(uint32_t /*id*/, bool& prohibited)
25 {
26     prohibited = true;
27 }
28 
29 void deleteIsNotProhibitedMock(uint32_t /*id*/, bool& prohibited)
30 {
31     prohibited = false;
32 }
33 
34 // Test that the update timestamp changes when the resolved property changes
35 TEST(TestUpdateTS, testChangeResolved)
36 {
37     // Setting resolved will serialize, so need this directory.
38     fs::create_directories(paths::error());
39 
40     if (!fs::exists(paths::error()))
41     {
42         ADD_FAILURE() << "Could not create " << paths::error() << "\n";
43         exit(1);
44     }
45 
46     auto bus = sdbusplus::bus::new_default();
47     phosphor::logging::internal::Manager manager(bus, OBJ_INTERNAL);
48 
49     // Use a random number for the ID to avoid other CI
50     // testcases running in parallel.
51     std::srand(std::time(nullptr));
52     uint32_t id = std::rand();
53 
54     if (fs::exists(fs::path{paths::error()} / std::to_string(id)))
55     {
56         std::cerr << "Another testcase is using ID " << id << "\n";
57         id = std::rand();
58     }
59 
60     uint64_t timestamp{100};
61     std::string message{"test error"};
62     std::string fwLevel{"level42"};
63     std::string path{"/tmp/99"};
64     std::vector<std::string> testData{"additional", "data"};
65     phosphor::logging::AssociationList associations{};
66 
67     Entry elog{bus,
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                path,
77                manager};
78 
79     EXPECT_EQ(elog.timestamp(), elog.updateTimestamp());
80 
81     std::this_thread::sleep_for(1ms);
82 
83     elog.resolved(true);
84     auto updateTS = elog.updateTimestamp();
85     EXPECT_NE(updateTS, elog.timestamp());
86 
87     std::this_thread::sleep_for(1ms);
88 
89     elog.resolved(false);
90     EXPECT_NE(updateTS, elog.updateTimestamp());
91     updateTS = elog.updateTimestamp();
92 
93     std::this_thread::sleep_for(1ms);
94 
95     // No change
96     elog.resolved(false);
97     EXPECT_EQ(updateTS, elog.updateTimestamp());
98 
99     // Leave the directory in case other CI instances are running
100     fs::remove(fs::path{paths::error()} / std::to_string(id));
101 }
102 
103 TEST(TestResolveProhibited, testResolveFlagChange)
104 {
105     auto persist_path = phosphor::logging::paths::error();
106 
107     // Setting resolved will serialize, so need this directory.
108     fs::create_directories(persist_path);
109 
110     if (!fs::exists(persist_path))
111     {
112         ADD_FAILURE() << "Could not create "
113                       << phosphor::logging::paths::error() << "\n";
114         exit(1);
115     }
116 
117     auto bus = sdbusplus::bus::new_default();
118     phosphor::logging::internal::Manager manager(bus, OBJ_INTERNAL);
119 
120     // Use a random number for the ID to avoid other CI
121     // testcases running in parallel.
122     std::srand(std::time(nullptr));
123     uint32_t id = std::rand();
124 
125     if (fs::exists(persist_path / std::to_string(id)))
126     {
127         std::cerr << "Another testcase is using ID " << id << "\n";
128         id = std::rand();
129     }
130 
131     uint64_t timestamp{100};
132     std::string message{"test error"};
133     std::string fwLevel{"level42"};
134     std::string path{"/tmp/99"};
135     std::vector<std::string> testData{"additional", "data"};
136     phosphor::logging::AssociationList associations{};
137 
138     Entry elog{bus,
139                std::string(OBJ_ENTRY) + '/' + std::to_string(id),
140                id,
141                timestamp,
142                Entry::Level::Informational,
143                std::move(message),
144                std::move(testData),
145                std::move(associations),
146                fwLevel,
147                path,
148                manager};
149 
150     Extensions ext{deleteIsProhibitedMock};
151 
152     EXPECT_THROW(elog.resolved(true),
153                  sdbusplus::xyz::openbmc_project::Common::Error::Unavailable);
154 
155     Extensions::getDeleteProhibitedFunctions().clear();
156 
157     Extensions e{deleteIsNotProhibitedMock};
158 
159     EXPECT_NO_THROW(elog.resolved(true));
160     EXPECT_EQ(elog.resolved(), true);
161 
162     // Leave the directory in case other CI instances are running
163     fs::remove(persist_path / std::to_string(id));
164 }
165 } // namespace test
166 } // namespace logging
167 } // namespace phosphor
168