diff options
author | Roland Reichwein <mail@reichwein.it> | 2023-01-21 19:05:43 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2023-01-21 19:05:43 +0100 |
commit | c464265f60ddd367786b08f5d49cd7a6d650b7d6 (patch) | |
tree | d2c747cc041a92d38ac1d25eb47fc7e398d5af7b /tests/test-whiteboard.cpp | |
parent | 3d0592e9238a59df54b3e3b757a38fa2e7f0ccfb (diff) |
First websocket connection
Diffstat (limited to 'tests/test-whiteboard.cpp')
-rw-r--r-- | tests/test-whiteboard.cpp | 120 |
1 files changed, 119 insertions, 1 deletions
diff --git a/tests/test-whiteboard.cpp b/tests/test-whiteboard.cpp index 46c4bae..b183021 100644 --- a/tests/test-whiteboard.cpp +++ b/tests/test-whiteboard.cpp @@ -1,21 +1,39 @@ #include <gtest/gtest.h> +#include <cstring> #include <filesystem> #include <memory> #include <string> #include <system_error> +#include <boost/process/child.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/beast/core.hpp> +#include <boost/beast/http.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/asio/buffers_iterator.hpp> +#include <boost/asio/connect.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/local/stream_protocol.hpp> + +#include <unistd.h> + #include "libreichwein/file.h" +#include "libreichwein/process.h" #include "config.h" #include "storage.h" #include "whiteboard.h" +namespace bp = boost::process; namespace fs = std::filesystem; using namespace Reichwein; +using namespace std::string_literals; namespace { const fs::path webserverConfigFilename{"./webserver.conf"}; + const fs::path testConfigFilename{"./whiteboard.conf"}; const fs::path testDbFilename{"./whiteboard.db3"}; } @@ -25,20 +43,55 @@ class Webserver public: Webserver() { + File::setFile(webserverConfigFilename, R"CONFIG( +<webserver> + <user>www-data</user> + <group>www-data</group> + <threads>10</threads> + <statisticspath>stats.db</statisticspath> + <plugin-directory>../plugins</plugin-directory> + <sites> + <site> + <host>[::1]</host> + <path requested="/"> + <plugin>websocket</plugin> + <target>::1:9876</target> + </path> + </site> + </sites> + <sockets> + <socket> + <address>::1</address> + <port>8080</port> + <protocol>http</protocol> + <site>localhost</site> + </socket> + </sockets> +</webserver> +)CONFIG"); + start(); } ~Webserver() { stop(); + fs::remove(webserverConfigFilename); } - void runInBackground() + void start() { + m_child = bp::child("/usr/bin/webserver"s, "-c"s, webserverConfigFilename.generic_string()); + Process::wait_for_pid_listening_on(m_child.id(), 8080); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); } void stop() { + m_child.terminate(); } + +private: + bp::child m_child; }; class WhiteboardTest: public ::testing::Test @@ -54,27 +107,92 @@ protected: { File::setFile(testConfigFilename, R"CONFIG( <config> + <port>::1:9876</port> <datapath>.</datapath> <maxage>2592000</maxage> + <threads>4</threads> </config> )CONFIG"); std::error_code ec; fs::remove(testDbFilename, ec); m_config = std::make_shared<Config>(testConfigFilename); + + //m_webserver = std::make_shared<Webserver>(webserverConfigFilename); + + m_pid = fork(); + if (m_pid == -1) { + throw std::runtime_error("Error on fork(): "s + strerror(errno)); + } else if (m_pid == 0) { // child + Whiteboard whiteboard; + std::vector<std::string> argvv{{"whiteboard", "-c", testConfigFilename.generic_string()}}; + char* argv[] = {argvv[0].data(), argvv[1].data(), argvv[2].data(), nullptr}; + whiteboard.run(argvv.size(), argv); + exit(0); + } + Process::wait_for_pid_listening_on(m_pid, 9876); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); } void TearDown() override { + if (m_pid == 0) + throw std::runtime_error("Whiteboard not running on requesting SIGTERM"); + + if (kill(m_pid, SIGTERM) != 0) + throw std::runtime_error("Unable to SIGTERM Whiteboard"); + + if (int result = waitpid(m_pid, NULL, 0); result != m_pid) + throw std::runtime_error("waitpid returned "s + std::to_string(result)); + std::error_code ec; fs::remove(testDbFilename, ec); fs::remove(testConfigFilename, ec); } std::shared_ptr<Config> m_config; + //std::shared_ptr<Webserver> m_webserver; + pid_t m_pid{}; }; TEST_F(WhiteboardTest, connection) { + std::string host = "::1"; + auto const port = "9876" ; + + // The io_context is required for all I/O + boost::asio::io_context ioc; + + // These objects perform our I/O + boost::asio::ip::tcp::resolver resolver{ioc}; + boost::beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ioc}; + + // Look up the domain name + auto const results = resolver.resolve(host, port); + + // Make the connection on the IP address we get from a lookup + auto ep = boost::asio::connect(boost::beast::get_lowest_layer(ws), results); + + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + if (host == "::1") + host = "[" + host + "]"; + host += ':' + std::to_string(ep.port()); + + // Set a decorator to change the User-Agent of the handshake + ws.set_option(boost::beast::websocket::stream_base::decorator( + [](boost::beast::websocket::request_type& req) + { + req.set(boost::beast::http::field::user_agent, + std::string("Reichwein.IT Test Websocket Client")); + })); + + // Perform the websocket handshake + ws.handshake(host, "/"); +} + +TEST_F(WhiteboardTest, getfile) +{ } |