summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-12 10:04:13 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-12 10:04:13 +0100
commit3cb78411178f8458f889975799060e0bb866d2cf (patch)
treeb05192fa8997d94986ba20a58b1fb268d992ca75
parent2f8a7cce46603755cc44dd16907030ae0b778635 (diff)
Speed up webserver tests by improving wait for server
-rw-r--r--tests/test-webserver.cpp81
1 files changed, 79 insertions, 2 deletions
diff --git a/tests/test-webserver.cpp b/tests/test-webserver.cpp
index 077c27e..727356d 100644
--- a/tests/test-webserver.cpp
+++ b/tests/test-webserver.cpp
@@ -59,10 +59,84 @@ const fs::path testConfigFilename{"./webserver.conf"};
const fs::path testCertFilename{"./testchain.pem"};
const fs::path testKeyFilename{"./testkey.pem"};
+// tcp: tcp or tcp6
+bool tcp_is_pid_listening_on(const std::string& tcp, pid_t pid, int port)
+{
+ std::string filename{fmt::format("/proc/{}/net/{}", pid, tcp)};
+ std::ifstream f{filename, std::ios::in};
+ // e.g.:
+ // sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
+ // 0: 00000000:C799 00000000:0000 0A 00000000:00000000 00:00000000 00000000 107 0 21869 1 00000000335416a4 100 0 0 10 0
+ std::string s;
+ std::getline(f, s); // skip head line
+ while (std::getline(f, s)) {
+ boost::algorithm::trim_left(s);
+
+ size_t pos_space1{s.find(' ')};
+ if (pos_space1 == std::string::npos)
+ throw std::runtime_error("Expected first space in " + filename);
+
+ size_t pos_colon1{s.find(':', pos_space1 + 1)};
+ if (pos_colon1 == std::string::npos)
+ throw std::runtime_error("Expected first colon in " + filename);
+
+ size_t pos_space2{s.find(' ', pos_colon1 + 1)};
+ if (pos_space2 == std::string::npos)
+ throw std::runtime_error("Expected second space in " + filename);
+
+ std::string port_s{s.substr(pos_colon1 + 1, pos_space2 - (pos_colon1 + 1))};
+ auto current_port{std::stoul(port_s, nullptr, 16)};
+ if (current_port != port)
+ continue;
+
+ // now, we are in a line related to matching local port
+
+ size_t pos_space3{s.find(' ', pos_space2 + 1)};
+ if (pos_space3 == std::string::npos)
+ throw std::runtime_error("Expected third space in " + filename);
+
+ size_t pos_space4{s.find(' ', pos_space3 + 1)};
+ if (pos_space4 == std::string::npos)
+ throw std::runtime_error("Expected fourth space in " + filename);
+
+ std::string state_s{s.substr(pos_space3 + 1, pos_space4 - (pos_space3 + 1))};
+ if (state_s == "0A") // listening state TCP_LISTEN, from net/tcp_states.h
+ return true;
+ }
+
+ return false; // not found
+}
+
+bool is_pid_listening_on(pid_t pid, int port)
+{
+ return tcp_is_pid_listening_on("tcp", pid, port) || tcp_is_pid_listening_on("tcp6", pid, port);
+}
+
+void wait_for_pid_listening_on(pid_t pid, int port)
+{
+ while (!is_pid_listening_on(pid, port)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+}
+
+// returns -1 if no port found in config
+int port_from_config(const std::string& config)
+{
+ pt::ptree tree;
+ std::istringstream stream{config};
+ pt::read_xml(stream, tree);
+ try {
+ return tree.get<int>("webserver.sockets.socket.port");
+ } catch(...) {
+ return -1;
+ }
+}
+
class WebserverProcess
{
void init(const std::string& config)
{
+ m_config = config;
File::setFile(testConfigFilename, config);
// test self signed certificate
@@ -202,7 +276,9 @@ public:
}
// wait for server to start up
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ if (int port{port_from_config(m_config)}; port >= 0)
+ wait_for_pid_listening_on(m_pid, port);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
void stop()
@@ -247,6 +323,7 @@ public:
private:
pid_t m_pid;
+ std::string m_config;
// child stdout
std::shared_ptr<__gnu_cxx::stdio_filebuf<char>> m_filebuf;
@@ -576,7 +653,7 @@ public:
exit(0);
}
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ wait_for_pid_listening_on(m_pid, 8765);
}
void stop()