From d8bbf880d4208dbea4a3e4ef80c909f25cef84a5 Mon Sep 17 00:00:00 2001 From: deniskovalchuk Date: Wed, 27 Mar 2024 00:51:08 +0300 Subject: [PATCH] test: add ftp::test::server class --- test/CMakeLists.txt | 1 + test/client.cpp | 69 ++++++--------------------------- test/test_server.hpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 58 deletions(-) create mode 100644 test/test_server.hpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6487a66..8b6163b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,6 +24,7 @@ set(sources reply.cpp test_helpers.cpp test_helpers.hpp + test_server.hpp utils.cpp) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) diff --git a/test/client.cpp b/test/client.cpp index e4d8d48..8cdaa6a 100644 --- a/test/client.cpp +++ b/test/client.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include "test_helpers.hpp" +#include "test_server.hpp" namespace { @@ -96,40 +96,21 @@ class client : public testing::Test protected: static void SetUpTestSuite() { - std::optional server_path = get_test_server_path(); - - if (!server_path) - return; - - boost::filesystem::path python = get_python_path(); - - if (python.empty()) - return; - - std::filesystem::create_directory(server_root_dir_); - - /* Run test server. Usage: python server.py port root_directory */ - boost::process::ipstream server_output; - server_process_ - = boost::process::child(python, server_path.value(), "2121", server_root_dir_, - boost::process::std_out > boost::process::null, - boost::process::std_err > server_output); - - while (server_process_.running()) + try { - std::string line; - std::getline(server_output, line); - - if (line.find("starting FTP server") != std::string::npos) - break; + server_.start(server_root_dir_, 2121); + } + catch (const std::exception & ex) + { + GTEST_SKIP() << "Skip. Test FTP server is not running: " << ex.what(); } } static void TearDownTestSuite() { - if (server_process_.running()) + if (server_.running()) { - server_process_.terminate(); + server_.stop(); } std::filesystem::remove_all(server_root_dir_); @@ -137,7 +118,7 @@ class client : public testing::Test void SetUp() override { - if (!server_process_.running()) + if (!server_.running()) { GTEST_SKIP() << "Skip. Test FTP server is not running."; } @@ -156,36 +137,8 @@ class client : public testing::Test } private: - static std::optional get_test_server_path() - { - const char *path = std::getenv("LIBFTP_TEST_SERVER_PATH"); - - if (path) - { - return { path }; - } - else - { - return std::nullopt; - } - } - - static boost::filesystem::path get_python_path() - { - boost::filesystem::path path = boost::process::search_path("python3"); - - if (path.empty()) - { - return boost::process::search_path("python"); - } - else - { - return path; - } - } - inline static std::string server_root_dir_ = "server_root"; - inline static boost::process::child server_process_; + inline static ftp::test::server server_; }; TEST_F(client, open_connection) diff --git a/test/test_server.hpp b/test/test_server.hpp new file mode 100644 index 0000000..bb5568e --- /dev/null +++ b/test/test_server.hpp @@ -0,0 +1,90 @@ +/* + * MIT License + * + * Copyright (c) 2024 Denis Kovalchuk + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef LIBFTP_TEST_SERVER_HPP +#define LIBFTP_TEST_SERVER_HPP + +#include +#include +#include +#include + +namespace ftp::test +{ + +class server +{ +public: + void start(const std::string & root_directory, std::uint16_t port) + { + const char *server_path = std::getenv("LIBFTP_TEST_SERVER_PATH"); + if (!server_path) + { + throw std::runtime_error("LIBFTP_TEST_SERVER_PATH is not set."); + } + + boost::filesystem::path python_path = boost::process::search_path("python3"); + if (python_path.empty()) + { + python_path = boost::process::search_path("python"); + if (python_path.empty()) + { + throw std::runtime_error("Python is not found."); + } + } + + std::filesystem::create_directory(root_directory); + + /* Usage: python server.py port root_directory */ + boost::process::ipstream output; + process_ = boost::process::child(python_path, server_path, std::to_string(port), root_directory, + boost::process::std_out > boost::process::null, + boost::process::std_err > output); + + while (process_.running()) + { + std::string line; + std::getline(output, line); + + if (line.find("starting FTP server") != std::string::npos) + break; + } + } + + [[nodiscard]] bool running() + { + return process_.running(); + } + + void stop() + { + process_.terminate(); + } + +private: + boost::process::child process_; +}; + +} // namespace ftp::test +#endif //LIBFTP_TEST_SERVER_HPP