diff options
author | Roland Reichwein <mail@reichwein.it> | 2023-03-03 16:55:33 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2023-03-03 16:55:33 +0100 |
commit | 96476044387e98ee1ee7a6eb992b521bd447813c (patch) | |
tree | caffaaef53a0afeafb5b68c460b42e98e72044c4 /tests/test-whiteboard.cpp | |
parent | c9fa963e71258c5adfb71cf1996cd1bcb33df0bb (diff) |
Diffstat (limited to 'tests/test-whiteboard.cpp')
-rw-r--r-- | tests/test-whiteboard.cpp | 255 |
1 files changed, 0 insertions, 255 deletions
diff --git a/tests/test-whiteboard.cpp b/tests/test-whiteboard.cpp deleted file mode 100644 index 3f70bcf..0000000 --- a/tests/test-whiteboard.cpp +++ /dev/null @@ -1,255 +0,0 @@ -#include <gtest/gtest.h> - -#include <cstring> -#include <filesystem> -#include <memory> -#include <regex> -#include <string> -#include <system_error> -#include <thread> - -#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"}; -} - -class WhiteboardTest: public ::testing::Test -{ -protected: - WhiteboardTest(){ - } - - ~WhiteboardTest() override{ - } - - void SetUp() override - { - File::setFile(testConfigFilename, R"CONFIG( -<config> - <port>::1:9876</port> - <datapath>.</datapath> - <maxage>2592000</maxage> - <threads>4</threads> - <maxconnections>3</maxconnections> -</config> -)CONFIG"); - std::error_code ec; - fs::remove(testDbFilename, ec); - - m_config = std::make_shared<Config>(testConfigFilename); - - 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; - pid_t m_pid{}; -}; - -class WebsocketClient -{ -public: - WebsocketClient() - { - std::string host = "::1"; - auto const port = "9876" ; - - // These objects perform our I/O - boost::asio::ip::tcp::resolver resolver{ioc_}; - ws_ = std::make_unique<boost::beast::websocket::stream<boost::asio::ip::tcp::socket>>(ioc_); - - // Look up the domain name - resolver_results_ = resolver.resolve(host, port); - - connect(); - handshake(); - } - - void connect() - { - // Make the connection on the IP address we get from a lookup - ep_ = boost::asio::connect(boost::beast::get_lowest_layer(*ws_), resolver_results_); - } - - void handshake() - { - // 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 - std::string host{"[::1]:9876"}; - - // 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, "/"); - - } - - void write(const std::string& data) - { - ws_->write(boost::asio::buffer(data)); - } - - std::string read() - { - boost::beast::flat_buffer buffer; - ws_->read(buffer); - return {boost::asio::buffers_begin(buffer.data()), boost::asio::buffers_end(buffer.data())}; - } - - ~WebsocketClient() - { - } - - bool is_open() - { - return ws_->is_open(); - } - -private: - boost::asio::io_context ioc_; - boost::asio::ip::tcp::resolver::results_type resolver_results_; - std::unique_ptr<boost::beast::websocket::stream<boost::asio::ip::tcp::socket>> ws_; - boost::asio::ip::tcp::endpoint ep_; -}; - -// -// tests via websocket server in separate process (hides coverage) -// - -TEST_F(WhiteboardTest, websocket_server_connection) -{ - WebsocketClient wc; -} - -TEST_F(WhiteboardTest, websocket_server_generate_id) -{ - WebsocketClient wc; - - wc.write("<request><command>newid</command></request>"); - std::string result0 {wc.read()}; - ASSERT_TRUE(boost::algorithm::starts_with(result0, "<serverinfo><type>newid</type><id>")); - ASSERT_TRUE(boost::algorithm::ends_with(result0, "</id></serverinfo>")); - ASSERT_EQ(result0.size(), 58); - - wc.write("<request><command>newid</command></request>"); - std::string result1 {wc.read()}; - ASSERT_TRUE(boost::algorithm::starts_with(result1, "<serverinfo><type>newid</type><id>")); - ASSERT_TRUE(boost::algorithm::ends_with(result1, "</id></serverinfo>")); - ASSERT_EQ(result1.size(), 58); - - ASSERT_NE(result0, result1); -} - -// check number of threads as configured -TEST_F(WhiteboardTest, threads) -{ - ASSERT_GE(Process::number_of_threads(m_pid), 4); -} - -TEST_F(WhiteboardTest, max_connections) -{ - WebsocketClient wc1; - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - ASSERT_TRUE(wc1.is_open()); - - WebsocketClient wc2; - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - ASSERT_TRUE(wc2.is_open()); - - WebsocketClient wc3; - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - ASSERT_TRUE(wc3.is_open()); - - ASSERT_THROW(WebsocketClient wc4, std::exception); -} - -TEST_F(WhiteboardTest, id) -{ - WebsocketClient wc; - - wc.write("<request><command>getfile</command><id>1</id></request>"); - std::string result {wc.read()}; - - EXPECT_EQ(result, "<serverinfo><type>getfile</type><data/><revision>0</revision><pos>0</pos></serverinfo>"); - - wc.write("<request><command>getfile</command><id></id></request>"); - result = wc.read(); - EXPECT_EQ(result, "<serverinfo><type>error</type><message>Message handling error: Invalid id (empty)</message></serverinfo>"); - - wc.write("<request><command>getfile</command><id>01234567890123456789</id></request>"); - result = wc.read(); - EXPECT_EQ(result, "<serverinfo><type>error</type><message>Message handling error: Invalid id (size > 16)</message></serverinfo>"); - - wc.write("<request><command>getfile</command><id>X</id></request>"); - result = wc.read(); - EXPECT_EQ(result, "<serverinfo><type>error</type><message>Message handling error: Invalid id char: X</message></serverinfo>"); - - wc.write("<request><command>getfile</command><id>a.</id></request>"); - result = wc.read(); - EXPECT_EQ(result, "<serverinfo><type>error</type><message>Message handling error: Invalid id char: .</message></serverinfo>"); - - wc.write("<request><command>getfile</command><id>a$b</id></request>"); - result = wc.read(); - EXPECT_EQ(result, "<serverinfo><type>error</type><message>Message handling error: Invalid id char: $</message></serverinfo>"); -} - |