| #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 "async_resp.hpp" | |
| #include "dbus_utility.hpp" | |
| #include <nlohmann/json.hpp> | |
| #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(*mock_managed_store_instance_, | |
| setProperty("service", "path", "interface", "property", | |
| dbus::utility::DbusVariantType{"bad_command"}, _)) | |
| .Times(1) | |
| .WillOnce(SimulateFailedAsyncSetPropertyDbusCallAction:: | |
| SimulateFailedAsyncSetPropertyDbusCall(io_error)); | |
| mock_managed_store_instance_->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(*mock_managed_store_instance_, | |
| setProperty("service", "path", "interface", "property", | |
| dbus::utility::DbusVariantType{"good_command"}, _)) | |
| .Times(1) | |
| .WillOnce(SimulateSuccessfulAsyncSetPropertyDbusCallAction:: | |
| SimulateSuccessfulAsyncSetPropertyDbusCall()); | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| PostDbusCallToIoContextThreadSafe( | |
| _, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), | |
| "service", "path", "interface", "method")) | |
| .Times(1) | |
| .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeAction:: | |
| SimulateSuccessfulAsyncPostDbusCall()); | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| PostDbusCallToIoContextThreadSafe( | |
| _, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), | |
| "service", "path", "interface", "method")) | |
| .Times(1) | |
| .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeAction:: | |
| SimulateFailedAsyncPostDbusCall()); | |
| mock_managed_store_instance_->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( | |
| mock_managed_store_instance_->getMockObjectFromManagedStore(key).ok()); | |
| EXPECT_TRUE(mock_managed_store_instance_ | |
| ->upsertMockObjectIntoManagedStore(key, original_test_value) | |
| .ok()); | |
| absl::StatusOr<std::shared_ptr<ValueType>> obtained_test_value = | |
| mock_managed_store_instance_->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(mock_managed_store_instance_ | |
| ->upsertMockObjectIntoManagedStore(key, original_test_value) | |
| .ok()); | |
| std::shared_ptr<ValueType> updated_test_value = | |
| CreateValueType(DbusVariantType("test_value_updated")); | |
| EXPECT_TRUE(mock_managed_store_instance_ | |
| ->upsertMockObjectIntoManagedStore(key, updated_test_value) | |
| .ok()); | |
| absl::StatusOr<std::shared_ptr<ValueType>> obtained_test_value = | |
| mock_managed_store_instance_->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(mock_managed_store_instance_ | |
| ->upsertMockObjectIntoManagedStore(key, original_test_value) | |
| .ok()); | |
| EXPECT_TRUE( | |
| mock_managed_store_instance_->evictMockObjectFromManagedStore(key).ok()); | |
| EXPECT_FALSE( | |
| mock_managed_store_instance_->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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(mock_managed_store_instance_ | |
| ->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( | |
| *mock_managed_store_instance_, | |
| 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))); | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| PostDbusCallToIoContextThreadSafe( | |
| _, | |
| An<absl::AnyInvocable<void(const boost::system::error_code&, | |
| const std::vector<DurationType>&)>&&>(), | |
| "service", "path", "interface", "method")) | |
| .Times(1) | |
| .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction:: | |
| SimulateFailedAsyncPostDbusCallWithEmptyValue()); | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| 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))); | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| 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)); | |
| mock_managed_store_instance_->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(mock_managed_store_instance_ | |
| ->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; | |
| mock_managed_store_instance_->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(mock_managed_store_instance_ | |
| ->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; | |
| mock_managed_store_instance_->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; | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| 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))); | |
| mock_managed_store_instance_->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( | |
| *mock_managed_store_instance_, | |
| 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))); | |
| mock_managed_store_instance_->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()); | |
| } | |
| TEST_F( | |
| MockManagedStoreTest, | |
| ValidateFailedPostDbusCallWithStringRetMsgAndFdWithExactMessageAndError) { | |
| std::shared_ptr<bmcweb::AsyncResp> async_resp = | |
| std::make_shared<bmcweb::AsyncResp>(); | |
| sdbusplus::message_t expected_msg = sdbusplus::message_t(); | |
| EXPECT_CALL( | |
| *mock_managed_store_instance_, | |
| PostDbusCallWithStringRetMsgAndFd( | |
| _, | |
| 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))); | |
| mock_managed_store_instance_->PostDbusCallWithStringRetMsgAndFd( | |
| 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 |