| #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 |