|  | #include "test/g3/mock_managed_store_test.hpp" | 
|  |  | 
|  | #include <unistd.h> | 
|  |  | 
|  | #include <cstddef> | 
|  | #include <cstdint> | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <tuple> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include <gmock/gmock.h> | 
|  | #include <gtest/gtest.h> | 
|  | #include "absl/functional/any_invocable.h" | 
|  | #include "absl/status/statusor.h" | 
|  | #include "boost/asio/detail/exception.hpp" | 
|  | #include "boost/asio/io_context.hpp"  // NOLINT | 
|  | #include "boost/beast/http/message.hpp"  //NOLINT | 
|  | #include "boost/beast/http/string_body.hpp"  //NOLINT | 
|  | #include "boost/coroutine/exceptions.hpp" | 
|  | #include "boost/system/detail/errc.hpp" | 
|  | #include "boost/system/detail/error_code.hpp" | 
|  | #include "redfish_v1.pb.h" | 
|  | #include "nlohmann/json.hpp" | 
|  | #include "dbus_utility.hpp" // NOLINT | 
|  | #include "async_resp.hpp" // NOLINT | 
|  | #include "http_request.hpp" // NOLINT | 
|  | #include "managed_store.hpp" | 
|  | #include "managed_store_types.hpp" | 
|  | #include "test/g3/mock_managed_store.hpp" | 
|  | #include "sdbusplus/message.hpp" | 
|  | #include "sdbusplus/message/native_types.hpp" | 
|  |  | 
|  | namespace managedStore { | 
|  | namespace { | 
|  |  | 
|  | using ::dbus::utility::DBusInteracesMap; | 
|  | using ::dbus::utility::DBusPropertiesMap; | 
|  | using ::dbus::utility::DbusVariantType; | 
|  | using ::dbus::utility::ManagedObjectType; | 
|  | using ::dbus::utility::MapperGetObject; | 
|  | using ::dbus::utility::MapperGetSubTreePathsResponse; | 
|  | using ::dbus::utility::MapperGetSubTreeResponse; | 
|  | using ::dbus::utility::MapperServiceMap; | 
|  | using ::dbus::utility::SystemdListUnits; | 
|  |  | 
|  | using ::testing::_; | 
|  | using ::testing::An; | 
|  | using ::testing::ElementsAre; | 
|  |  | 
|  | using ManagedType = managedStore::ManagedType; | 
|  | using DurationType = std::tuple<std::string, int64_t>; | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateSetPropertyMockWithFailedDbusCall) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  |  | 
|  | boost::system::error_code io_error = | 
|  | boost::system::errc::make_error_code(boost::system::errc::io_error); | 
|  |  | 
|  | EXPECT_CALL(*managedStore::GetManagedObjectStore(), | 
|  | setProperty("service", "path", "interface", "property", | 
|  | dbus::utility::DbusVariantType{"bad_command"}, _)) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateFailedAsyncSetPropertyDbusCallAction:: | 
|  | SimulateFailedAsyncSetPropertyDbusCall(io_error)); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->setProperty( | 
|  | "service", "path", "interface", "property", | 
|  | dbus::utility::DbusVariantType{"bad_command"}, | 
|  | [async_resp](const boost::system::error_code& ec) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue["status"] = ec.value(); | 
|  | return; | 
|  | } | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "success"})"); | 
|  | }); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], io_error.value()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateSetPropertyMockWithSuccessfulDbusCall) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  |  | 
|  | EXPECT_CALL(*managedStore::GetManagedObjectStore(), | 
|  | setProperty("service", "path", "interface", "property", | 
|  | dbus::utility::DbusVariantType{"good_command"}, _)) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateSuccessfulAsyncSetPropertyDbusCallAction:: | 
|  | SimulateSuccessfulAsyncSetPropertyDbusCall()); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->setProperty( | 
|  | "service", "path", "interface", "property", | 
|  | dbus::utility::DbusVariantType{"good_command"}, | 
|  | [async_resp](const boost::system::error_code& ec) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | return; | 
|  | } | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "success"})"); | 
|  | }); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], "success"); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateSuccessfulPostDbusCallToIoContextMock) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  |  | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeAction:: | 
|  | SimulateSuccessfulAsyncPostDbusCall()); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | return; | 
|  | } | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "success"})"); | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], "success"); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateFailedPostDbusCallToIoContextMock) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  |  | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeAction:: | 
|  | SimulateFailedAsyncPostDbusCall()); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | return; | 
|  | } | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "success"})"); | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], "error"); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, VerifyUpsertCorrectlyAddsObjectInManagedStore) { | 
|  | DbusVariantType test_value("test_value"); | 
|  | KeyType key(ManagedType::kManagedProperty, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = CreateValueType(test_value); | 
|  | EXPECT_FALSE(managedStore::GetManagedObjectStore() | 
|  | ->getMockObjectFromManagedStore(key) | 
|  | .ok()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  |  | 
|  | absl::StatusOr<std::shared_ptr<ValueType>> obtained_test_value = | 
|  | managedStore::GetManagedObjectStore()->getMockObjectFromManagedStore(key); | 
|  | ASSERT_TRUE(obtained_test_value.ok()); | 
|  | EXPECT_EQ((*obtained_test_value)->serialize(), | 
|  | original_test_value->serialize()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, VerifyUpsertCorrectlyUpdatesObjectInManagedStore) { | 
|  | KeyType key(ManagedType::kManagedProperty, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(DbusVariantType("test_value")); | 
|  |  | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  |  | 
|  | std::shared_ptr<ValueType> updated_test_value = | 
|  | CreateValueType(DbusVariantType("test_value_updated")); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, updated_test_value) | 
|  | .ok()); | 
|  |  | 
|  | absl::StatusOr<std::shared_ptr<ValueType>> obtained_test_value = | 
|  | managedStore::GetManagedObjectStore()->getMockObjectFromManagedStore(key); | 
|  | ASSERT_TRUE(obtained_test_value.ok()); | 
|  | EXPECT_EQ((*obtained_test_value)->serialize(), | 
|  | updated_test_value->serialize()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, VerifyEvictCorrectlyUpdatesObjectInManagedStore) { | 
|  | KeyType key(ManagedType::kManagedProperty, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(DbusVariantType("test_value")); | 
|  |  | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  |  | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->evictMockObjectFromManagedStore(key) | 
|  | .ok()); | 
|  |  | 
|  | EXPECT_FALSE(managedStore::GetManagedObjectStore() | 
|  | ->getMockObjectFromManagedStore(key) | 
|  | .ok()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, IncorrectKeyTypeAndValueTypeUpsertThrowsError) { | 
|  | KeyType key(ManagedType::kManagedObject, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(DbusVariantType("test_value")); | 
|  |  | 
|  | EXPECT_FALSE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  |  | 
|  | // These are sample ways of creating a Mocked Dbus Object | 
|  |  | 
|  | // Top Level | 
|  | // ObjectPath -> InterfaceMap | 
|  | // Get each interface of the object | 
|  |  | 
|  | // Interface Map | 
|  | // Interface -> PropertyMap | 
|  | // Get each property of the interface | 
|  |  | 
|  | // PropertyMap | 
|  | // PropertyName -> PropertyValue | 
|  | // Get each property value of the property name | 
|  |  | 
|  | ManagedObjectType CreateDummyManagedObjectType() { | 
|  | return ManagedObjectType({std::make_pair( | 
|  | sdbusplus::message::object_path("path"), | 
|  | DBusInteracesMap({std::make_pair( | 
|  | "interface", DBusPropertiesMap({std::make_pair( | 
|  | "property", DbusVariantType("test_value"))}))}))}); | 
|  | } | 
|  |  | 
|  | // Top Level | 
|  | // Service to list of interfaces | 
|  |  | 
|  | MapperGetObject CreateDummyMapperGetObject() { | 
|  | return MapperGetObject({{"service", {"interface1", "interface2"}}}); | 
|  | } | 
|  |  | 
|  | // Top Level | 
|  | // Property value | 
|  |  | 
|  | DbusVariantType CreateDummyDbusVariantType() { | 
|  | return DbusVariantType("test_value"); | 
|  | } | 
|  |  | 
|  | // Top Level | 
|  | // PropertyName -> PropertyValue | 
|  | // Get each property value of the property name | 
|  |  | 
|  | DBusPropertiesMap CreateDummyDBusPropertiesMap() { | 
|  | return DBusPropertiesMap( | 
|  | {std::make_pair("property", DbusVariantType("test_value"))}); | 
|  | } | 
|  |  | 
|  | // Top Level | 
|  | // Object path -> MapperServiceMap | 
|  | // Get the service map of the object path | 
|  |  | 
|  | // MapperServiceMap | 
|  | // Service -> list of interfaces | 
|  | // Get the list of interfaces of the service | 
|  |  | 
|  | MapperGetSubTreeResponse CreateDummyMapperGetSubTreeResponse() { | 
|  | return MapperGetSubTreeResponse({std::make_pair( | 
|  | "path", MapperServiceMap({{"service", {"interface1", "interface2"}}}))}); | 
|  | } | 
|  |  | 
|  | // Top Level | 
|  | // List of Object Paths | 
|  |  | 
|  | MapperGetSubTreePathsResponse CreateDummyMapperGetSubTreePathsResponse() { | 
|  | return MapperGetSubTreePathsResponse({"path1", "path2"}); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, CorrectlyUpsertEveryManagedTypeIntoManagedStore) { | 
|  | // kManagedProperty | 
|  | { | 
|  | KeyType key(ManagedType::kManagedProperty, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", | 
|  | "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyDbusVariantType()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | // kManagedObject | 
|  | { | 
|  | KeyType key(ManagedType::kManagedObject, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", | 
|  | "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyManagedObjectType()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | // kManagedMapperObject | 
|  | { | 
|  | KeyType key(ManagedType::kManagedMapperObject, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", | 
|  | "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyMapperGetObject()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | // kManagedProperty | 
|  | { | 
|  | KeyType key(ManagedType::kManagedProperty, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", | 
|  | "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyDbusVariantType()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | // kManagedPropertyMap | 
|  | { | 
|  | KeyType key(ManagedType::kManagedPropertyMap, "service", | 
|  | sdbusplus::message::object_path("path"), "interface", | 
|  | "property"); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyDBusPropertiesMap()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | // kManagedSubtree | 
|  | { | 
|  | KeyType key(ManagedType::kManagedSubtree, "path", 9, {"interfaces"}); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyMapperGetSubTreeResponse()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | // kManagedSubtreePaths | 
|  | { | 
|  | KeyType key(ManagedType::kManagedSubtreePaths, "path", 29, {"interfaces"}); | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(CreateDummyMapperGetSubTreePathsResponse()); | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateSuccessfulPostDbusCallWithValue) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | const std::vector<DurationType> expected_durations = {{"test_value", 123}}; | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, | 
|  | An<absl::AnyInvocable<void(const boost::system::error_code&, | 
|  | const std::vector<DurationType>&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction< | 
|  | std::vector<DurationType>>:: | 
|  | SimulateSuccessfulAsyncPostDbusCallWithValue( | 
|  | std::make_shared<std::vector<DurationType>>( | 
|  | expected_durations))); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec, | 
|  | const std::vector<DurationType>& duration) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | return; | 
|  | } | 
|  | async_resp->res.jsonValue["Members"] = duration; | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_NE(async_resp->res.jsonValue["status"], "error"); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue.contains("Members")); | 
|  | nlohmann::json& members = async_resp->res.jsonValue["Members"]; | 
|  | EXPECT_EQ(members.size(), 1); | 
|  | size_t index = 0; | 
|  | for (nlohmann::json& member : members) { | 
|  | EXPECT_EQ(member, expected_durations[index++]); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateFailedPostDbusCallWithValue) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, | 
|  | An<absl::AnyInvocable<void(const boost::system::error_code&, | 
|  | const std::vector<DurationType>&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction:: | 
|  | SimulateFailedAsyncPostDbusCallWithEmptyValue()); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec, | 
|  | const std::vector<DurationType>& duration) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | async_resp->res.jsonValue["Members"] = duration; | 
|  | return; | 
|  | } | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], "error"); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue.contains("Members")); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue["Members"].empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, | 
|  | ValidateSuccessfulPostDbusCallForGetRequestsWithValue) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | const std::vector<DurationType> expected_durations = {{"test_value", 123}}; | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, | 
|  | An<absl::AnyInvocable<void(const boost::system::error_code&, | 
|  | const std::vector<DurationType>&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction< | 
|  | std::vector<DurationType>>:: | 
|  | SimulateSuccessfulAsyncPostDbusCallWithValue( | 
|  | std::make_shared<std::vector<DurationType>>( | 
|  | expected_durations))); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec, | 
|  | const std::vector<DurationType>& duration) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | return; | 
|  | } | 
|  | async_resp->res.jsonValue["Members"] = duration; | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_NE(async_resp->res.jsonValue["status"], "error"); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue.contains("Members")); | 
|  | nlohmann::json& members = async_resp->res.jsonValue["Members"]; | 
|  | EXPECT_EQ(members.size(), 1); | 
|  | size_t index = 0; | 
|  | for (nlohmann::json& member : members) { | 
|  | EXPECT_EQ(member, expected_durations[index++]); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, | 
|  | ValidateFailedPostDbusCallForGetRequestsWithValue) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | boost::system::error_code io_error = | 
|  | boost::system::errc::make_error_code(boost::system::errc::io_error); | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, | 
|  | An<absl::AnyInvocable<void(const boost::system::error_code&, | 
|  | const std::vector<DurationType>&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction:: | 
|  | SimulateFailedAsyncPostDbusCallWithEmptyValue(io_error)); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec, | 
|  | const std::vector<DurationType>& duration) { | 
|  | if (ec) { | 
|  | async_resp->res.jsonValue["status"] = ec.value(); | 
|  | async_resp->res.jsonValue["Members"] = duration; | 
|  | return; | 
|  | } | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | EXPECT_FALSE(async_resp->res.jsonValue.contains("status")); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], io_error.value()); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue.contains("Members")); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue["Members"].empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateGetSubTreePathsResponseWithUpsert) { | 
|  | KeyType key(ManagedType::kManagedSubtreePaths, "path", 0, {"interfaces"}); | 
|  | std::vector<std::string> insert_paths = {"path1", "path2"}; | 
|  | std::shared_ptr<ValueType> original_test_value = | 
|  | CreateValueType(std::move(insert_paths)); | 
|  |  | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  |  | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | managedStore::ManagedObjectStoreContext context(async_resp); | 
|  | std::vector<std::string> response_paths; | 
|  | bool is_error = false; | 
|  | managedStore::GetManagedObjectStore()->getSubTreePaths( | 
|  | "path", 0, {{"interfaces"}}, context, | 
|  | [&is_error, &response_paths](const boost::system::error_code& ec, | 
|  | const std::vector<std::string>& paths) { | 
|  | if (ec) { | 
|  | is_error = true; | 
|  | return; | 
|  | } | 
|  | response_paths = paths; | 
|  | }); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_FALSE(is_error); | 
|  | EXPECT_THAT(response_paths, ElementsAre("path1", "path2")); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateFailedGetSubTreePathsResponse) { | 
|  | KeyType key(ManagedType::kManagedSubtreePaths, "path", 0, {"interfaces"}); | 
|  | std::vector<std::string> insert_paths = {"path1", "path2"}; | 
|  | std::shared_ptr<ValueType> original_test_value = CreateErrorValueType( | 
|  | insert_paths, boost::system::error_code(boost::asio::error::not_found)); | 
|  |  | 
|  | EXPECT_TRUE(managedStore::GetManagedObjectStore() | 
|  | ->upsertMockObjectIntoManagedStore(key, original_test_value) | 
|  | .ok()); | 
|  |  | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | managedStore::ManagedObjectStoreContext context(async_resp); | 
|  | std::vector<std::string> response_paths; | 
|  | bool is_error = false; | 
|  | managedStore::GetManagedObjectStore()->getSubTreePaths( | 
|  | "path", 0, {{"interfaces"}}, context, | 
|  | [&is_error, &response_paths](const boost::system::error_code& ec, | 
|  | const std::vector<std::string>& paths) { | 
|  | if (ec) { | 
|  | is_error = true; | 
|  | return; | 
|  | } | 
|  | response_paths = paths; | 
|  | }); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_TRUE(is_error); | 
|  | EXPECT_TRUE(response_paths.empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, MissingEntryInManagedStoreReturnsError) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | managedStore::ManagedObjectStoreContext context(async_resp); | 
|  | std::vector<std::string> response_paths; | 
|  | bool is_error = false; | 
|  | managedStore::GetManagedObjectStore()->getSubTreePaths( | 
|  | "path", 0, {{"interfaces"}}, context, | 
|  | [&is_error, &response_paths](const boost::system::error_code& ec, | 
|  | const std::vector<std::string>& paths) { | 
|  | if (ec) { | 
|  | is_error = true; | 
|  | return; | 
|  | } | 
|  | response_paths = paths; | 
|  | }); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_TRUE(is_error); | 
|  | EXPECT_TRUE(response_paths.empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, ValidateFailedPostDbusCallWithExactError) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, | 
|  | An<absl::AnyInvocable<void(const boost::system::error_code&, | 
|  | const std::vector<DurationType>&)>&&>(), | 
|  | "service", "path", "interface", "method")) | 
|  | .Times(1) | 
|  | .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction:: | 
|  | SimulateFailedAsyncPostDbusCallWithEmptyValue( | 
|  | boost::system::errc::make_error_code( | 
|  | boost::system::errc::io_error))); | 
|  |  | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp](const boost::system::error_code& ec, | 
|  | const std::vector<DurationType>& duration) { | 
|  | if (ec) { | 
|  | if (ec == boost::system::errc::io_error) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "io_error"})"); | 
|  | } else { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | } | 
|  | async_resp->res.jsonValue["Members"] = duration; | 
|  | return; | 
|  | } | 
|  | }, | 
|  | "service", "path", "interface", "method"); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], "io_error"); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue.contains("Members")); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue["Members"].empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(MockManagedStoreTest, | 
|  | ValidateFailedPostDbusCallWithExactMessageAndError) { | 
|  | std::shared_ptr<bmcweb::AsyncResp> async_resp = | 
|  | std::make_shared<bmcweb::AsyncResp>(); | 
|  | sdbusplus::message_t expected_msg = sdbusplus::message_t(); | 
|  | EXPECT_CALL( | 
|  | *managedStore::GetManagedObjectStore(), | 
|  | PostDbusCallToIoContextThreadSafe( | 
|  | _, | 
|  | An<absl::AnyInvocable<void(const boost::system::error_code&, | 
|  | const sdbusplus::message_t&, | 
|  | const sdbusplus::message::unix_fd&)>&&>(), | 
|  | "service", "path", "interface", "method", "arg")) | 
|  | .Times(1) | 
|  | .WillOnce( | 
|  | SimulateFailedAsyncPostDbusCallThreadSafeWithMsgAndEmptyValueAction:: | 
|  | SimulateFailedAsyncPostDbusCallWithMsgAndEmptyValue( | 
|  | expected_msg, boost::system::errc::make_error_code( | 
|  | boost::system::errc::io_error))); | 
|  | managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe( | 
|  | nullptr, | 
|  | [async_resp, expected_msg](const boost::system::error_code& ec, | 
|  | const sdbusplus::message_t& msg, | 
|  | const sdbusplus::message::unix_fd& /*fd*/) { | 
|  | if (ec) { | 
|  | if (ec == boost::system::errc::io_error && msg.is_method_error()) { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "io_error"})"); | 
|  | } else { | 
|  | async_resp->res.jsonValue = | 
|  | nlohmann::json::parse(R"({"status": "error"})"); | 
|  | } | 
|  | return; | 
|  | } | 
|  | }, | 
|  | "service", "path", "interface", "method", "arg"); | 
|  |  | 
|  | RunIoUntilDone(); | 
|  |  | 
|  | EXPECT_EQ(async_resp->res.jsonValue["status"], "io_error"); | 
|  | EXPECT_TRUE(async_resp->res.jsonValue["Members"].empty()); | 
|  | } | 
|  | }  // namespace | 
|  | }  // namespace managedStore |