diff options
author | Roland Reichwein <mail@reichwein.it> | 2023-01-04 19:54:48 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2023-01-04 19:54:48 +0100 |
commit | fb7219b2f8553cebc9871427fed134ad4b162bac (patch) | |
tree | 0175af394574b1c1a91d784b08291a3553d5d8b0 | |
parent | 685a7e3407a8450ce71ff9d7dea94de6d4847e65 (diff) |
HTTP GET tests
-rw-r--r-- | tests/test-webserver.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/tests/test-webserver.cpp b/tests/test-webserver.cpp index 9321169..aa09a01 100644 --- a/tests/test-webserver.cpp +++ b/tests/test-webserver.cpp @@ -12,6 +12,7 @@ #include <boost/test/data/monomorphic.hpp> #include <boost/test/data/test_case.hpp> +#include <boost/algorithm/string.hpp> #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #ifdef BOOST_LATEST @@ -34,9 +35,10 @@ #include <string> #include <thread> -#include <unistd.h> +#include <ext/stdio_filebuf.h> #include <signal.h> #include <sys/wait.h> +#include <unistd.h> #include <libreichwein/file.h> @@ -118,16 +120,36 @@ public: if (m_pid != 0) throw std::runtime_error("Process already running, so it can't be started"); + // connect stdout of new child process to stream of parent, via pipe + int filedes[2]; + if (pipe(filedes) == -1) + throw std::runtime_error("Pipe error"); + m_pid = fork(); if (m_pid < 0) throw std::runtime_error("Fork unsuccessful."); if (m_pid == 0) { // child process branch + // + if (close(filedes[0]) == -1) + throw std::runtime_error("Child can't close read end of pipe"); + + // Replace stdout of child with pipe input (next 2 commands) + if (close(1) == -1) + throw std::runtime_error("Child can't close stdout"); + if (dup(filedes[1]) == -1) + throw std::runtime_error("Child replace stdout w/ pipe input"); + char* argv[] = {(char*)"webserver", (char*)"-c", (char*)"./webserver.conf"}; webserver(sizeof(argv) / sizeof(char*), argv); exit(0); } + if (close(filedes[1]) == -1) + throw std::runtime_error("Parent can't close read end of pipe"); + m_filebuf = std::make_shared<__gnu_cxx::stdio_filebuf<char>>(filedes[0], std::ios::in); + m_is = std::make_shared<std::istream>(&(*m_filebuf)); + // wait for server to start up std::this_thread::sleep_for(std::chrono::milliseconds(100)); } @@ -144,6 +166,8 @@ public: throw std::runtime_error("waitpid returned "s + std::to_string(result)); m_pid = 0; + m_is = 0; + m_filebuf = 0; } bool isRunning() @@ -168,8 +192,28 @@ public: return state == "R" || state == "S"; } + std::string output() + { + if (!isRunning()) + throw std::runtime_error("No output/stdout available from webserver since it is not running"); + + if (!m_is) + throw std::runtime_error("Webserver stdout stream not initialized."); + + std::stringstream result; + std::string buffer(static_cast<std::string::size_type>(1024), '\0'); + int size{}; + while ((size = m_is->readsome(buffer.data(), buffer.size())) > 0) + result << buffer.substr(0, size); + return result.str(); + } + private: pid_t m_pid; + + // child stdout + std::shared_ptr<__gnu_cxx::stdio_filebuf<char>> m_filebuf; + std::shared_ptr<std::istream> m_is; }; std::pair<std::string,std::string> HTTPGet(const std::string& target, bool ipv6 = true, bool HTTP11 = true) @@ -323,5 +367,9 @@ BOOST_DATA_TEST_CASE_F(Fixture, http_download, data::make({false, true}) * data: BOOST_REQUIRE(serverProcess.isRunning()); auto response{(https ? HTTPSGet("/webserver.conf") : HTTPGet("/webserver.conf"))}; BOOST_REQUIRE(serverProcess.isRunning()); + BOOST_REQUIRE_EQUAL(response.first, "HTTP/1.1 200 OK\r\nServer: Reichwein.IT Webserver 1.17\r\nContent-Type: application/text\r\nContent-Length: 1021\r\n\r\n"); + BOOST_REQUIRE_EQUAL(response.second, File::getFile(serverProcess.testConfigFilename)); + auto output{serverProcess.output()}; + BOOST_REQUIRE_MESSAGE(boost::algorithm::contains(output, "Serving"), "Bad output: "s + output); } |