1 #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 17 namespace phosphor::logging::test 18 { 19 using LoggingCleared = sdbusplus::event::xyz::openbmc_project::Logging::Cleared; 20 using LoggingEntry = sdbusplus::client::xyz::openbmc_project::logging::Entry<>; 21 22 // Fixture to spawn the log-manager for dbus-based testing. 23 class 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. 91 TEST_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. 100 TEST_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. 112 TEST_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 154