blob: ac33ded431d339a966abe85fe9fdb4d903ee0bd0 [file] [log] [blame]
Patrick Williamsf0af3582024-10-10 16:32:32 -04001#include "config.h"
2
3#include "log_manager.hpp"
4#include "paths.hpp"
5
6#include <phosphor-logging/commit.hpp>
7#include <sdbusplus/async.hpp>
8#include <sdbusplus/server/manager.hpp>
9#include <xyz/openbmc_project/Logging/Entry/client.hpp>
10#include <xyz/openbmc_project/Logging/event.hpp>
11
12#include <thread>
13
14#include <gmock/gmock.h>
15#include <gtest/gtest.h>
16
17namespace phosphor::logging::test
18{
19using LoggingCleared = sdbusplus::event::xyz::openbmc_project::Logging::Cleared;
20using LoggingEntry = sdbusplus::client::xyz::openbmc_project::logging::Entry<>;
21
22// Fixture to spawn the log-manager for dbus-based testing.
23class TestLogManagerDbus : public ::testing::Test
24{
25 protected:
26 // Create the daemon and sdbusplus::async::contexts.
27 void SetUp() override
28 {
29 // The daemon requires directories to be created first.
30 std::filesystem::create_directories(phosphor::logging::paths::error());
31
32 data = std::make_unique<fixture_data>();
33 }
34
35 // Stop the daemon, etc.
36 void TearDown() override
37 {
38 data.reset();
39 }
40
41 /** Run a client task, wait for it to complete, and stop daemon. */
42 template <typename T>
43 void run(T&& t)
44 {
45 data->client_ctx.spawn(std::move(t) | stdexec::then([this]() {
46 data->stop(data->client_ctx);
47 }));
48 data->client_ctx.run();
49 }
50
51 // Data for the fixture.
52 struct fixture_data
53 {
54 fixture_data() :
55 client_ctx(), server_ctx(), objManager(server_ctx, OBJ_LOGGING),
56 iMgr(server_ctx, OBJ_INTERNAL), mgr(server_ctx, OBJ_LOGGING, iMgr)
57 {
58 // Create a thread for the daemon.
59 task = std::thread([this]() {
60 server_ctx.request_name(BUSNAME_LOGGING);
61 server_ctx.run();
62 });
63 }
64
65 ~fixture_data()
66 {
67 // Stop the server and wait for the thread to exit.
68 stop(server_ctx);
69 task.join();
70 }
71
72 // Spawn a task to gracefully shutdown an sdbusplus::async::context
73 static void stop(sdbusplus::async::context& ctx)
74 {
75 ctx.spawn(stdexec::just() |
76 stdexec::then([&ctx]() { ctx.request_stop(); }));
77 }
78
79 sdbusplus::async::context client_ctx;
80 sdbusplus::async::context server_ctx;
81 sdbusplus::server::manager_t objManager;
82 internal::Manager iMgr;
83 Manager mgr;
84 std::thread task;
85 };
86
87 std::unique_ptr<fixture_data> data;
88};
89
90// Ensure we can successfully create and throw an sdbusplus event.
91TEST_F(TestLogManagerDbus, GenerateSimpleEvent)
92{
93 EXPECT_THROW(
94 { throw LoggingCleared("NUMBER_OF_LOGS", 1); }, LoggingCleared);
95 return;
96}
97
98// Call the synchronous version of the commit function and verify that the
99// daemon gives us a path.
100TEST_F(TestLogManagerDbus, CallCommitSync)
101{
102 auto path = lg2::commit(LoggingCleared("NUMBER_OF_LOGS", 3));
103 ASSERT_FALSE(path.str.empty());
104 EXPECT_THAT(path.str,
105 ::testing::StartsWith(
106 std::filesystem::path(LoggingEntry::namespace_path::value) /
107 LoggingEntry::namespace_path::entry));
108}
109
110// Call the asynchronous version of the commit function and verify that the
111// metadata is saved correctly.
112TEST_F(TestLogManagerDbus, CallCommitAsync)
113{
114 sdbusplus::message::object_path path{};
115 std::string log_count{};
116
117 auto create_log = [this, &path, &log_count]() -> sdbusplus::async::task<> {
118 // Log an event.
119 path = co_await lg2::commit(data->client_ctx,
120 LoggingCleared("NUMBER_OF_LOGS", 6));
121
122 // Grab the additional data.
123 auto additionalData = co_await LoggingEntry(data->client_ctx)
124 .service(Entry::default_service)
125 .path(path.str)
126 .additional_data();
127
128 // Extract the NUMBER_OF_LOGS.
129 for (const auto& value : additionalData)
130 {
131 if (value.starts_with("NUMBER_OF_LOGS="))
132 {
133 log_count = value.substr(value.find_first_of('=') + 1);
134 }
135 }
136
137 co_return;
138 };
139
140 run(create_log());
141
142 ASSERT_FALSE(path.str.empty());
143 ASSERT_FALSE(log_count.empty());
144
145 EXPECT_THAT(path.str,
146 ::testing::StartsWith(
147 std::filesystem::path(LoggingEntry::namespace_path::value) /
148 LoggingEntry::namespace_path::entry));
149
150 EXPECT_EQ(log_count, "6");
151}
152
153} // namespace phosphor::logging::test