blob: a50d42a1f5887e93a3dc1c933beee961d1e3ebca [file] [log] [blame] [edit]
#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