160 lines
5 KiB
C++
160 lines
5 KiB
C++
|
#include <gtest/gtest.h>
|
||
|
|
||
|
#include <boost/asio/co_spawn.hpp>
|
||
|
#include <boost/asio/detached.hpp>
|
||
|
#include <boost/asio/ip/tcp.hpp>
|
||
|
#include <larra/features.hpp>
|
||
|
#include <larra/impl/mock_socket.hpp>
|
||
|
#include <larra/raw_xml_stream.hpp>
|
||
|
#include <utempl/utils.hpp>
|
||
|
|
||
|
namespace larra::xmpp {
|
||
|
|
||
|
constexpr std::string_view kDoc = "<doc></doc>\n<doc2></doc2>\n<doc3/>";
|
||
|
|
||
|
constexpr std::string_view kDoc2 = "<doc></doc>\n<doc2></doc2>";
|
||
|
|
||
|
constexpr std::string_view kDoc3 =
|
||
|
"<stream:features><mechanisms "
|
||
|
"xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism><mechanism>SCRAM-SHA-256</mechanism><mechanism>X-OAUTH2</"
|
||
|
"mechanism></mechanisms><register xmlns='http://jabber.org/features/iq-register'/></stream:features>";
|
||
|
|
||
|
TEST(RawXmlStream, ReadByOne) {
|
||
|
boost::asio::io_context context;
|
||
|
bool error{};
|
||
|
|
||
|
boost::asio::co_spawn(
|
||
|
context,
|
||
|
// NOLINTNEXTLINE: Safe
|
||
|
[&] -> boost::asio::awaitable<void> {
|
||
|
RawXmlStream stream{impl::MockSocket{context.get_executor(), 1}};
|
||
|
stream.AddReceivedData(kDoc);
|
||
|
try {
|
||
|
auto doc = co_await stream.Read();
|
||
|
auto node = doc->get_root_node();
|
||
|
EXPECT_EQ(node->get_name(), std::string_view{"doc"});
|
||
|
EXPECT_FALSE(node->has_child_text());
|
||
|
auto doc2 = co_await stream.Read();
|
||
|
auto node2 = doc2->get_root_node();
|
||
|
EXPECT_EQ(node2->get_name(), std::string_view{"doc2"});
|
||
|
EXPECT_FALSE(node2->has_child_text());
|
||
|
|
||
|
} catch(const std::exception& err) {
|
||
|
SPDLOG_ERROR("{}", err.what());
|
||
|
error = true;
|
||
|
}
|
||
|
},
|
||
|
boost::asio::detached);
|
||
|
|
||
|
context.run();
|
||
|
EXPECT_FALSE(error);
|
||
|
}
|
||
|
|
||
|
TEST(RawXmlStream, ReadAll) {
|
||
|
boost::asio::io_context context;
|
||
|
bool error{};
|
||
|
boost::asio::co_spawn(
|
||
|
context, // NOLINTNEXTLINE: Safe
|
||
|
[&] -> boost::asio::awaitable<void> {
|
||
|
RawXmlStream stream{impl::MockSocket{context.get_executor(), kDoc.size()}};
|
||
|
stream.AddReceivedData(kDoc);
|
||
|
try {
|
||
|
auto doc = co_await stream.Read();
|
||
|
auto node = doc->get_root_node();
|
||
|
EXPECT_EQ(node->get_name(), std::string_view{"doc"});
|
||
|
EXPECT_FALSE(node->has_child_text());
|
||
|
auto doc2 = co_await stream.Read();
|
||
|
auto node2 = doc2->get_root_node();
|
||
|
EXPECT_EQ(node2->get_name(), std::string_view{"doc2"});
|
||
|
EXPECT_FALSE(node2->has_child_text());
|
||
|
|
||
|
} catch(const std::exception& err) {
|
||
|
SPDLOG_ERROR("{}", err.what());
|
||
|
error = true;
|
||
|
}
|
||
|
},
|
||
|
boost::asio::detached);
|
||
|
context.run();
|
||
|
EXPECT_FALSE(error);
|
||
|
}
|
||
|
|
||
|
TEST(RawXmlStream, ReadAllWithEnd) {
|
||
|
boost::asio::io_context context;
|
||
|
bool error{};
|
||
|
boost::asio::co_spawn(
|
||
|
context, // NOLINTNEXTLINE: Safe
|
||
|
[&] -> boost::asio::awaitable<void> {
|
||
|
RawXmlStream stream{impl::MockSocket{context.get_executor(), kDoc2.size()}};
|
||
|
stream.AddReceivedData(kDoc2);
|
||
|
try {
|
||
|
auto doc = co_await stream.Read();
|
||
|
auto node = doc->get_root_node();
|
||
|
EXPECT_EQ(node->get_name(), std::string_view{"doc"});
|
||
|
EXPECT_FALSE(node->has_child_text());
|
||
|
auto doc2 = co_await stream.Read();
|
||
|
auto node2 = doc2->get_root_node();
|
||
|
EXPECT_EQ(node2->get_name(), std::string_view{"doc2"});
|
||
|
EXPECT_FALSE(node2->has_child_text());
|
||
|
|
||
|
} catch(const std::exception& err) {
|
||
|
SPDLOG_ERROR("{}", err.what());
|
||
|
error = true;
|
||
|
}
|
||
|
},
|
||
|
boost::asio::detached);
|
||
|
context.run();
|
||
|
EXPECT_FALSE(error);
|
||
|
}
|
||
|
|
||
|
TEST(RawXmlStream, ReadFeatures) {
|
||
|
boost::asio::io_context context;
|
||
|
bool error{};
|
||
|
boost::asio::co_spawn(
|
||
|
context, // NOLINTNEXTLINE: Safe
|
||
|
[&] -> boost::asio::awaitable<void> {
|
||
|
RawXmlStream stream{impl::MockSocket{context.get_executor(), kDoc3.size()}};
|
||
|
stream.AddReceivedData(kDoc3);
|
||
|
try {
|
||
|
auto features = co_await stream.template Read<StreamFeatures>();
|
||
|
} catch(const std::exception& err) {
|
||
|
SPDLOG_ERROR("{}", err.what());
|
||
|
error = true;
|
||
|
}
|
||
|
},
|
||
|
boost::asio::detached);
|
||
|
context.run();
|
||
|
EXPECT_FALSE(error);
|
||
|
}
|
||
|
|
||
|
struct SomeStruct {
|
||
|
static constexpr auto kDefaultName = "some";
|
||
|
static constexpr auto kDefaultNamespace = "namespace";
|
||
|
static constexpr auto kPrefix = "prefix";
|
||
|
friend auto operator<<(xmlpp::Element* node, const SomeStruct&) {
|
||
|
node->add_child_text("text");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
TEST(RawXmlStream, Write) {
|
||
|
boost::asio::io_context context;
|
||
|
bool error{};
|
||
|
boost::asio::co_spawn(
|
||
|
context, // NOLINTNEXTLINE: Safe
|
||
|
[&] -> boost::asio::awaitable<void> {
|
||
|
RawXmlStream stream1{impl::MockSocket{context.get_executor()}};
|
||
|
auto stream = std::move(stream1);
|
||
|
try {
|
||
|
co_await stream.Send(SomeStruct{});
|
||
|
EXPECT_EQ(stream.GetSentData(), std::string_view{"<prefix:some xmlns:prefix=\"namespace\">text</prefix:some>"});
|
||
|
} catch(const std::exception& err) {
|
||
|
SPDLOG_ERROR("{}", err.what());
|
||
|
error = true;
|
||
|
}
|
||
|
},
|
||
|
boost::asio::detached);
|
||
|
context.run();
|
||
|
EXPECT_FALSE(error);
|
||
|
}
|
||
|
|
||
|
} // namespace larra::xmpp
|