diff options
| author | Roland Reichwein <mail@reichwein.it> | 2023-01-12 10:04:13 +0100 | 
|---|---|---|
| committer | Roland Reichwein <mail@reichwein.it> | 2023-01-12 10:04:13 +0100 | 
| commit | 3cb78411178f8458f889975799060e0bb866d2cf (patch) | |
| tree | b05192fa8997d94986ba20a58b1fb268d992ca75 | |
| parent | 2f8a7cce46603755cc44dd16907030ae0b778635 (diff) | |
Speed up webserver tests by improving wait for server
| -rw-r--r-- | tests/test-webserver.cpp | 81 | 
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() | 
