| #include "redfish_resource.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "gmock.h" |
| #include "gunit.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "nlohmann/json_fwd.hpp" |
| #include "mock_redfish_plugin.h" |
| #include "proxy.h" |
| #include "redfish_plugin.h" |
| #include "request_response.h" |
| #include "voyager/deferrable_priority_queue.hpp" |
| |
| namespace { |
| |
| using ::milotic::Host; |
| using ::milotic::Proxy; |
| using ::milotic::ProxyRequest; |
| using ::milotic::ProxyResponse; |
| using ::milotic::RedfishPlugin; |
| |
| using ::testing::AllOf; |
| using ::testing::HasSubstr; |
| using ::testing::MockFunction; |
| using ::testing::Pointee; |
| using ::testing::Property; |
| using ::testing::Return; |
| using ::testing::SaveArgPointee; |
| using ::testing::StrictMock; |
| using ::testing::status::StatusIs; |
| |
| TEST(RedfishResourceTest, GetValidResourceOk) { |
| constexpr absl::string_view resource = R"json({ |
| "@odata.id": "/redfish/v1", |
| "Name": "Service Root" |
| })json"; |
| |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, "/redfish/v1")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| ASSERT_OK_AND_ASSIGN(nlohmann::json response, |
| milotic::GetRedfishResource(&proxy, "/redfish/v1")); |
| EXPECT_TRUE(response.is_object()); |
| EXPECT_EQ(response["@odata.id"], "/redfish/v1"); |
| EXPECT_EQ(response["Name"], "Service Root"); |
| } |
| |
| TEST(RedfishResourceTest, HttpErrorIsReported) { |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, "/redfish/v1")))) |
| .WillOnce(Return( |
| ProxyResponse{{.code = 404, .body = "<<<error report string>>>"}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| EXPECT_THAT(milotic::GetRedfishResource(&proxy, "/redfish/v1"), |
| StatusIs(absl::StatusCode::kUnavailable, |
| AllOf(HasSubstr("404"), |
| HasSubstr("<<<error report string>>>")))); |
| } |
| |
| TEST(RedfishResourceTest, JsonParseErrorIsReported) { |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, "/redfish/v1")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body = "<<<bad json>>>"}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| EXPECT_THAT( |
| milotic::GetRedfishResource(&proxy, "/redfish/v1"), |
| StatusIs(absl::StatusCode::kInternal, HasSubstr("<<<bad json>>>"))); |
| } |
| |
| TEST(RedfishResourceTest, ExpandAllIsAdded) { |
| constexpr absl::string_view resource = R"json({ |
| "@odata.id": "/redfish/v1", |
| "Name": "Service Root" |
| })json"; |
| |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, |
| "/redfish/v1?$expand=*($levels=1)")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| EXPECT_OK(milotic::GetRedfishResource( |
| &proxy, "/redfish/v1", {.expand_links = true, .expand_non_links = true})); |
| } |
| |
| TEST(RedfishResourceTest, ExpandWithoutLinksIsAdded) { |
| constexpr absl::string_view resource = R"json({ |
| "@odata.id": "/redfish/v1", |
| "Name": "Service Root" |
| })json"; |
| |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, |
| "/redfish/v1?$expand=.($levels=1)")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| EXPECT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", |
| {.expand_non_links = true})); |
| } |
| |
| TEST(RedfishResourceTest, ExpandOnlyLinksIsAdded) { |
| constexpr absl::string_view resource = R"json({ |
| "@odata.id": "/redfish/v1", |
| "Name": "Service Root" |
| })json"; |
| |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, |
| "/redfish/v1?$expand=~($levels=1)")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| EXPECT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", |
| {.expand_links = true})); |
| } |
| |
| TEST(RedfishResourceTest, ExpandLevelsSet) { |
| constexpr absl::string_view resource = R"json({ |
| "@odata.id": "/redfish/v1", |
| "Name": "Service Root" |
| })json"; |
| |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, |
| "/redfish/v1?$expand=~($levels=99)")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins); |
| |
| EXPECT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", |
| {.expand_links = true, .levels = 99})); |
| } |
| |
| TEST(RedfishResourceTest, AsyncGetValidResourceOk) { |
| constexpr absl::string_view resource = R"json({ |
| "@odata.id": "/redfish/v1", |
| "Name": "Service Root" |
| })json"; |
| |
| auto handler_plugin = std::make_unique<milotic::MockRedfishPlugin>(); |
| |
| EXPECT_CALL(*handler_plugin, Initialize).WillOnce(Return(absl::OkStatus())); |
| EXPECT_CALL(*handler_plugin, PreprocessRequest) |
| .WillOnce(Return(RedfishPlugin::RequestAction::kHandle)); |
| EXPECT_CALL( |
| *handler_plugin, |
| HandleRequest(RedfishPlugin::RequestVerb::kGet, |
| Pointee(Property(&ProxyRequest::GetPath, "/redfish/v1")))) |
| .WillOnce(Return(ProxyResponse{{.code = 200, .body{resource}}})); |
| |
| std::unique_ptr<RedfishPlugin> plugins[] = {std::move(handler_plugin)}; |
| voyager::DeferrablePriorityQueue queue(1); |
| Proxy proxy(Host::CreateTestHosts("test_endpoint"), plugins, &queue); |
| |
| absl::StatusOr<nlohmann::json> response; |
| |
| StrictMock<MockFunction<void(absl::StatusOr<nlohmann::json>)>> callback; |
| ASSERT_OK(milotic::GetRedfishResource(&proxy, "/redfish/v1", |
| callback.AsStdFunction())); |
| |
| EXPECT_CALL(callback, Call).WillOnce(SaveArgPointee<0>(&response)); |
| ASSERT_OK(queue.ProcessQueue(1)); |
| ASSERT_OK(response); |
| |
| EXPECT_TRUE(response->is_object()); |
| EXPECT_EQ(response.value()["@odata.id"], "/redfish/v1"); |
| EXPECT_EQ(response.value()["Name"], "Service Root"); |
| } |
| |
| } // namespace |