summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-04 19:54:48 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-04 19:54:48 +0100
commitfb7219b2f8553cebc9871427fed134ad4b162bac (patch)
tree0175af394574b1c1a91d784b08291a3553d5d8b0
parent685a7e3407a8450ce71ff9d7dea94de6d4847e65 (diff)
HTTP GET tests
-rw-r--r--tests/test-webserver.cpp50
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);
}