LogService: System dump calls common dump handlers

This patchset transitions System dump route handlers to the new style
of calling common dump handlers via std::bind_front() instead of
defining a lambda. BMC dump and FaultLog dump were previously
transitioned to the new style (see "LogService: Add support for Fault
Log" at https://gerrit.openbmc.org/c/openbmc/bmcweb/+/53175).

Note that System dump wasn't using a common dump handler for outputting
its LogService info (/redfish/v1/Systems/system/LogServices/Dump/)
before, so calling the common handler here is new.

No expected client impact.

Tested:

Get System dump LogService info:
curl -k -H "X-Auth-Token: $token" -X GET http://${bmc}/redfish/v1/Systems/system/LogServices/Dump/

(Diffed the ouput before and after applying this patchset and confirmed
they were equivalent except for the "DateTime", as expected. Also added
unit tests for getting dump LogService info.)

Create System dump entry. (Existing code for creating an entry via the
Redfish LogService action CollectDiagnosticData isn't currently working
for System dump, so instead directly call the corresponding D-Bus
method by running the following from the BMC console):
busctl call xyz.openbmc_project.Dump.Manager /xyz/openbmc_project/dump/system xyz.openbmc_project.Dump.Create CreateDump a{sv} 0

Get Entry:
curl -k -H "X-Auth-Token: $token" -X GET http://${bmc}/redfish/v1/Systems/system/LogServices/Dump/Entries/1

Get Entry Collection:
curl -k -H "X-Auth-Token: $token" -X GET http://${bmc}/redfish/v1/Systems/system/LogServices/Dump/Entries

Delete Entry:
curl -k -H "X-Auth-Token: $token" -X DELETE http://${bmc}/redfish/v1/Systems/system/LogServices/Dump/Entries/1

Clear Log:
curl -k -H "X-Auth-Token: $token" -X POST http://${bmc}/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog

Redfish Service Validator succeeded on the following URI tree:
/redfish/v1/Systems/system/LogServices/Dump

Signed-off-by: Claire Weinan <cweinan@google.com>
Change-Id: I5d66da17794c29672be8713481018bf3ce397ddf
diff --git a/meson.build b/meson.build
index c293e00..b3425be 100644
--- a/meson.build
+++ b/meson.build
@@ -400,6 +400,7 @@
   'include/ut/multipart_test.cpp',
   'include/ut/openbmc_dbus_rest_test.cpp',
   'redfish-core/include/utils/query_param_test.cpp',
+  'redfish-core/lib/ut/log_services_dump_test.cpp',
   'redfish-core/lib/ut/service_root_test.cpp',
   'redfish-core/lib/ut/thermal_subsystem_test.cpp',
   'redfish-core/lib/chassis_test.cpp',
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 2a26ab9..ffab320 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -2557,56 +2557,17 @@
 {
     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/")
         .privileges(redfish::privileges::getLogService)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        asyncResp->res.jsonValue["@odata.id"] =
-            "/redfish/v1/Systems/system/LogServices/Dump";
-        asyncResp->res.jsonValue["@odata.type"] =
-            "#LogService.v1_2_0.LogService";
-        asyncResp->res.jsonValue["Name"] = "Dump LogService";
-        asyncResp->res.jsonValue["Description"] = "System Dump LogService";
-        asyncResp->res.jsonValue["Id"] = "Dump";
-        asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
-
-        std::pair<std::string, std::string> redfishDateTimeOffset =
-            redfish::time_utils::getDateTimeOffsetNow();
-        asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
-        asyncResp->res.jsonValue["DateTimeLocalOffset"] =
-            redfishDateTimeOffset.second;
-
-        asyncResp->res.jsonValue["Entries"]["@odata.id"] =
-            "/redfish/v1/Systems/system/LogServices/Dump/Entries";
-        asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
-            "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog";
-
-        asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
-                                ["target"] =
-            "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData";
-        });
+        .methods(boost::beast::http::verb::get)(std::bind_front(
+            handleLogServicesDumpServiceGet, std::ref(app), "System"));
 }
 
 inline void requestRoutesSystemDumpEntryCollection(App& app)
 {
-
-    /**
-     * Functions triggers appropriate requests on DBus
-     */
     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/")
         .privileges(redfish::privileges::getLogEntryCollection)
         .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        getDumpEntryCollection(asyncResp, "System");
-        });
+            std::bind_front(handleLogServicesDumpEntriesCollectionGet,
+                            std::ref(app), "System"));
 }
 
 inline void requestRoutesSystemDumpEntry(App& app)
@@ -2614,31 +2575,14 @@
     BMCWEB_ROUTE(app,
                  "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/")
         .privileges(redfish::privileges::getLogEntry)
-
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& param) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        getDumpEntryById(asyncResp, param, "System");
-        });
+        .methods(boost::beast::http::verb::get)(std::bind_front(
+            handleLogServicesDumpEntryGet, std::ref(app), "System"));
 
     BMCWEB_ROUTE(app,
                  "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/")
         .privileges(redfish::privileges::deleteLogEntry)
-        .methods(boost::beast::http::verb::delete_)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& param) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        deleteDumpEntry(asyncResp, param, "system");
-        });
+        .methods(boost::beast::http::verb::delete_)(std::bind_front(
+            handleLogServicesDumpEntryDelete, std::ref(app), "System"));
 }
 
 inline void requestRoutesSystemDumpCreate(App& app)
@@ -2648,14 +2592,8 @@
         "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
         .privileges(redfish::privileges::postLogService)
         .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        createDump(asyncResp, req, "System");
-        });
+            std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
+                            std::ref(app), "System"));
 }
 
 inline void requestRoutesSystemDumpClear(App& app)
@@ -2664,17 +2602,8 @@
         app,
         "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog/")
         .privileges(redfish::privileges::postLogService)
-        .methods(boost::beast::http::verb::post)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-
-            {
-        if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-        {
-            return;
-        }
-        clearDump(asyncResp, "System");
-        });
+        .methods(boost::beast::http::verb::post)(std::bind_front(
+            handleLogServicesDumpClearLogPost, std::ref(app), "System"));
 }
 
 inline void requestRoutesCrashdumpService(App& app)
diff --git a/redfish-core/lib/ut/log_services_dump_test.cpp b/redfish-core/lib/ut/log_services_dump_test.cpp
new file mode 100644
index 0000000..192b79d
--- /dev/null
+++ b/redfish-core/lib/ut/log_services_dump_test.cpp
@@ -0,0 +1,117 @@
+#include "app.hpp"
+#include "event_service_manager.hpp"
+#include "include/async_resp.hpp"
+#include "redfish-core/lib/health.hpp"
+#include "redfish-core/lib/log_services.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace redfish
+{
+namespace
+{
+
+void assertLogServicesDumpServiceGet(crow::Response& res)
+{
+    nlohmann::json& json = res.jsonValue;
+    EXPECT_EQ(json["@odata.type"], "#LogService.v1_2_0.LogService");
+    EXPECT_EQ(json["Name"], "Dump LogService");
+}
+
+void assertLogServicesBMCDumpServiceGet(crow::Response& res)
+{
+    assertLogServicesDumpServiceGet(res);
+
+    nlohmann::json& json = res.jsonValue;
+    EXPECT_EQ(json["@odata.id"], "/redfish/v1/Managers/bmc/LogServices/Dump");
+    EXPECT_EQ(
+        json["Actions"]["#LogService.ClearLog"]["target"],
+        "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.ClearLog");
+    EXPECT_EQ(
+        json["Actions"]["#LogService.CollectDiagnosticData"]["target"],
+        "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData");
+    EXPECT_EQ(json["Description"], "BMC Dump LogService");
+    EXPECT_EQ(json["Entries"]["@odata.id"],
+              "/redfish/v1/Managers/bmc/LogServices/Dump/Entries");
+    EXPECT_EQ(json["Id"], "Dump");
+    EXPECT_EQ(json["OverWritePolicy"], "WrapsWhenFull");
+}
+
+void assertLogServicesFaultLogDumpServiceGet(crow::Response& res)
+{
+    assertLogServicesDumpServiceGet(res);
+
+    nlohmann::json& json = res.jsonValue;
+    EXPECT_EQ(json["@odata.id"],
+              "/redfish/v1/Managers/bmc/LogServices/FaultLog");
+    EXPECT_EQ(
+        json["Actions"]["#LogService.ClearLog"]["target"],
+        "/redfish/v1/Managers/bmc/LogServices/FaultLog/Actions/LogService.ClearLog");
+    EXPECT_EQ(json["Actions"]["#LogService.CollectDiagnosticData"]["target"],
+              nlohmann::detail::value_t::null);
+    EXPECT_EQ(json["Description"], "FaultLog Dump LogService");
+    EXPECT_EQ(json["Entries"]["@odata.id"],
+              "/redfish/v1/Managers/bmc/LogServices/FaultLog/Entries");
+    EXPECT_EQ(json["Id"], "FaultLog");
+    EXPECT_EQ(json["OverWritePolicy"], "Unknown");
+}
+
+void assertLogServicesSystemDumpServiceGet(crow::Response& res)
+{
+    assertLogServicesDumpServiceGet(res);
+
+    nlohmann::json& json = res.jsonValue;
+    EXPECT_EQ(json["@odata.id"], "/redfish/v1/Systems/system/LogServices/Dump");
+    EXPECT_EQ(
+        json["Actions"]["#LogService.ClearLog"]["target"],
+        "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog");
+    EXPECT_EQ(
+        json["Actions"]["#LogService.CollectDiagnosticData"]["target"],
+        "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData");
+    EXPECT_EQ(json["Description"], "System Dump LogService");
+    EXPECT_EQ(json["Entries"]["@odata.id"],
+              "/redfish/v1/Systems/system/LogServices/Dump/Entries");
+    EXPECT_EQ(json["Id"], "Dump");
+    EXPECT_EQ(json["OverWritePolicy"], "WrapsWhenFull");
+}
+
+TEST(LogServicesDumpServiceTest,
+     LogServicesBMCDumpServiceStaticAttributesAreExpected)
+{
+    auto shareAsyncResp = std::make_shared<bmcweb::AsyncResp>();
+    shareAsyncResp->res.setCompleteRequestHandler(
+        assertLogServicesBMCDumpServiceGet);
+    getDumpServiceInfo(shareAsyncResp, "BMC");
+}
+
+TEST(LogServicesDumpServiceTest,
+     LogServicesFaultLogDumpServiceStaticAttributesAreExpected)
+{
+    auto shareAsyncResp = std::make_shared<bmcweb::AsyncResp>();
+    shareAsyncResp->res.setCompleteRequestHandler(
+        assertLogServicesFaultLogDumpServiceGet);
+    getDumpServiceInfo(shareAsyncResp, "FaultLog");
+}
+
+TEST(LogServicesDumpServiceTest,
+     LogServicesSystemDumpServiceStaticAttributesAreExpected)
+{
+    auto shareAsyncResp = std::make_shared<bmcweb::AsyncResp>();
+    shareAsyncResp->res.setCompleteRequestHandler(
+        assertLogServicesSystemDumpServiceGet);
+    getDumpServiceInfo(shareAsyncResp, "System");
+}
+
+TEST(LogServicesDumpServiceTest, LogServicesInvalidDumpServiceGetReturnsError)
+{
+    auto shareAsyncResp = std::make_shared<bmcweb::AsyncResp>();
+    getDumpServiceInfo(shareAsyncResp, "Invalid");
+    EXPECT_EQ(shareAsyncResp->res.result(),
+              boost::beast::http::status::internal_server_error);
+}
+
+} // namespace
+} // namespace redfish