Files
clio/tests/unit/web/ng/ResponseTests.cpp
2026-03-24 15:25:32 +00:00

226 lines
8.1 KiB
C++

#include "util/MockAssert.hpp"
#include "util/Taggable.hpp"
#include "util/build/Build.hpp"
#include "util/config/ConfigDefinition.hpp"
#include "util/config/ConfigValue.hpp"
#include "util/config/Types.hpp"
#include "web/ng/MockConnection.hpp"
#include "web/ng/Request.hpp"
#include "web/ng/Response.hpp"
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/beast/http/field.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/status.hpp>
#include <boost/beast/http/string_body.hpp>
#include <boost/beast/http/verb.hpp>
#include <boost/json/object.hpp>
#include <boost/json/serialize.hpp>
#include <fmt/format.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>
#include <utility>
using namespace web::ng;
namespace http = boost::beast::http;
using namespace util::config;
struct ResponseAssertTest : common::util::WithMockAssert {};
TEST_F(ResponseAssertTest, intoHttpResponseWithoutHttpData)
{
Request::HttpHeaders const headers{};
Request const request{"some message", headers};
Response response{boost::beast::http::status::ok, "message", request};
EXPECT_CLIO_ASSERT_FAIL(std::move(response).intoHttpResponse());
}
TEST_F(ResponseAssertTest, asConstBufferWithHttpData)
{
Request const request{http::request<http::string_body>{http::verb::get, "/", 11}};
Response const response{boost::beast::http::status::ok, "message", request};
EXPECT_CLIO_ASSERT_FAIL(response.asWsResponse());
}
struct ResponseTest : testing::Test {
protected:
int const httpVersion_ = 11;
http::status const responseStatus_ = http::status::ok;
Request::HttpHeaders const headers_;
};
TEST_F(ResponseTest, intoHttpResponse)
{
Request const request{
http::request<http::string_body>{http::verb::post, "/", httpVersion_, "some message"}
};
std::string const responseMessage = "response message";
Response response{responseStatus_, responseMessage, request};
auto const httpResponse = std::move(response).intoHttpResponse();
EXPECT_EQ(httpResponse.result(), responseStatus_);
EXPECT_EQ(httpResponse.body(), responseMessage);
EXPECT_EQ(httpResponse.version(), httpVersion_);
EXPECT_EQ(httpResponse.keep_alive(), request.asHttpRequest()->get().keep_alive());
ASSERT_GT(httpResponse.count(http::field::content_type), 0);
EXPECT_EQ(httpResponse[http::field::content_type], "text/html");
ASSERT_GT(httpResponse.count(http::field::content_type), 0);
EXPECT_EQ(
httpResponse[http::field::server],
fmt::format("clio-server-{}", util::build::getClioVersionString())
);
}
TEST_F(ResponseTest, intoHttpResponseJson)
{
Request const request{
http::request<http::string_body>{http::verb::post, "/", httpVersion_, "some message"}
};
boost::json::object const responseMessage{{"key", "value"}};
Response response{responseStatus_, responseMessage, request};
auto const httpResponse = std::move(response).intoHttpResponse();
EXPECT_EQ(httpResponse.result(), responseStatus_);
EXPECT_EQ(httpResponse.body(), boost::json::serialize(responseMessage));
EXPECT_EQ(httpResponse.version(), httpVersion_);
EXPECT_EQ(httpResponse.keep_alive(), request.asHttpRequest()->get().keep_alive());
ASSERT_GT(httpResponse.count(http::field::content_type), 0);
EXPECT_EQ(httpResponse[http::field::content_type], "application/json");
ASSERT_GT(httpResponse.count(http::field::content_type), 0);
EXPECT_EQ(
httpResponse[http::field::server],
fmt::format("clio-server-{}", util::build::getClioVersionString())
);
}
TEST_F(ResponseTest, asConstBuffer)
{
Request const request("some request", headers_);
std::string const responseMessage = "response message";
Response const response{responseStatus_, responseMessage, request};
auto const buffer = response.asWsResponse();
EXPECT_EQ(buffer.size(), responseMessage.size());
std::string const messageFromBuffer{static_cast<char const*>(buffer.data()), buffer.size()};
EXPECT_EQ(messageFromBuffer, responseMessage);
}
TEST_F(ResponseTest, asConstBufferJson)
{
Request const request("some request", headers_);
boost::json::object const responseMessage{{"key", "value"}};
Response const response{responseStatus_, responseMessage, request};
auto const buffer = response.asWsResponse();
EXPECT_EQ(buffer.size(), boost::json::serialize(responseMessage).size());
std::string const messageFromBuffer{static_cast<char const*>(buffer.data()), buffer.size()};
EXPECT_EQ(messageFromBuffer, boost::json::serialize(responseMessage));
}
TEST_F(ResponseTest, createFromStringAndConnection)
{
util::TagDecoratorFactory const tagDecoratorFactory{ClioConfigDefinition{
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")}
}};
StrictMockConnection const connection{
"some ip", boost::beast::flat_buffer{}, tagDecoratorFactory
};
std::string const responseMessage = "response message";
EXPECT_CALL(connection, wasUpgraded()).WillOnce(testing::Return(false));
Response response{responseStatus_, responseMessage, connection};
EXPECT_EQ(response.message(), responseMessage);
auto const httpResponse = std::move(response).intoHttpResponse();
EXPECT_EQ(httpResponse.result(), responseStatus_);
auto const it = httpResponse.find(http::field::content_type);
ASSERT_NE(it, httpResponse.end());
EXPECT_EQ(it->value(), "text/html");
}
TEST_F(ResponseTest, createFromJsonAndConnection)
{
util::TagDecoratorFactory const tagDecoratorFactory{ClioConfigDefinition{
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("uint")}
}};
StrictMockConnection const connection{
"some ip", boost::beast::flat_buffer{}, tagDecoratorFactory
};
boost::json::object const responseMessage{{"key", "value"}};
EXPECT_CALL(connection, wasUpgraded()).WillOnce(testing::Return(false));
Response response{responseStatus_, responseMessage, connection};
EXPECT_EQ(response.message(), boost::json::serialize(responseMessage));
auto const httpResponse = std::move(response).intoHttpResponse();
EXPECT_EQ(httpResponse.result(), responseStatus_);
auto const it = httpResponse.find(http::field::content_type);
ASSERT_NE(it, httpResponse.end());
EXPECT_EQ(it->value(), "application/json");
}
TEST_F(ResponseTest, setMessageString_HttpResponse)
{
Request const request{
http::request<http::string_body>{http::verb::post, "/", httpVersion_, "some request"}
};
Response response{boost::beast::http::status::ok, "message", request};
std::string const newMessage = "new message";
response.setMessage(newMessage);
EXPECT_EQ(response.message(), newMessage);
auto const httpResponse = std::move(response).intoHttpResponse();
auto it = httpResponse.find(http::field::content_type);
ASSERT_NE(it, httpResponse.end());
EXPECT_EQ(it->value(), "text/html");
}
TEST_F(ResponseTest, setMessageString_WsResponse)
{
Request const request{"some request", headers_};
Response response{boost::beast::http::status::ok, "message", request};
std::string const newMessage = "new message";
response.setMessage(newMessage);
EXPECT_EQ(response.message(), newMessage);
}
TEST_F(ResponseTest, setMessageJson_HttpResponse)
{
Request const request{
http::request<http::string_body>{http::verb::post, "/", httpVersion_, "some request"}
};
Response response{boost::beast::http::status::ok, "message", request};
boost::json::object const newMessage{{"key", "value"}};
response.setMessage(newMessage);
auto const httpResponse = std::move(response).intoHttpResponse();
auto it = httpResponse.find(http::field::content_type);
ASSERT_NE(it, httpResponse.end());
EXPECT_EQ(it->value(), "application/json");
}
TEST_F(ResponseTest, setMessageJson_WsResponse)
{
Request const request{"some request", headers_};
Response response{boost::beast::http::status::ok, "message", request};
boost::json::object const newMessage{{"key", "value"}};
response.setMessage(newMessage);
EXPECT_EQ(response.message(), boost::json::serialize(newMessage));
}