LCOV - code coverage report
Current view: top level - corosio/test - temp_path.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 96.3 % 27 26 1
Test Date: 2026-05-20 17:06:58 Functions: 100.0 % 4 4

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Michael Vandeberg
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/corosio
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_COROSIO_TEST_TEMP_PATH_HPP
      11                 : #define BOOST_COROSIO_TEST_TEMP_PATH_HPP
      12                 : 
      13                 : #include <atomic>
      14                 : #include <cstdint>
      15                 : #include <cstdio>
      16                 : #include <filesystem>
      17                 : #include <random>
      18                 : #include <stdexcept>
      19                 : #include <string>
      20                 : #include <system_error>
      21                 : 
      22                 : namespace boost::corosio::test {
      23                 : 
      24                 : /** RAII temp directory holding a path for a Unix-domain socket.
      25                 : 
      26                 :     Creates a unique empty directory under
      27                 :     `std::filesystem::temp_directory_path()` and exposes a path under
      28                 :     it suitable for binding `local_stream_socket` /
      29                 :     `local_datagram_socket`. The destructor removes the directory
      30                 :     (and the bound socket file inside it) recursively, so tests that
      31                 :     throw mid-execution still clean up.
      32                 : 
      33                 :     Naming entropy comes from a process-wide atomic counter mixed with
      34                 :     a one-time `random_device` seed; that's enough to avoid collisions
      35                 :     between parallel test runs without requiring cryptographic
      36                 :     randomness. The constructor retries on collision and throws if it
      37                 :     cannot create a directory in a reasonable number of attempts.
      38                 : 
      39                 :     Platform note: the helper exists so tests don't need to call
      40                 :     `mkdtemp` / `unlink` / `rmdir` directly. On Windows, the path is
      41                 :     a filesystem AF_UNIX path (Windows 10 1803+).
      42                 : */
      43                 : class temp_socket_dir
      44                 : {
      45                 : public:
      46 HIT          20 :     temp_socket_dir()
      47              20 :     {
      48                 :         namespace fs = std::filesystem;
      49              20 :         auto const base = fs::temp_directory_path();
      50                 : 
      51                 :         // 64 bits of mixed entropy: a random seed established once
      52                 :         // at static init, XORed with a monotonic counter.
      53               3 :         static std::uint64_t const seed = [] {
      54               3 :             std::random_device rd;
      55               3 :             return (static_cast<std::uint64_t>(rd()) << 32) |
      56               6 :                    static_cast<std::uint64_t>(rd());
      57              23 :         }();
      58                 :         static std::atomic<std::uint64_t> counter{0};
      59                 : 
      60              20 :         std::error_code ec;
      61              20 :         for (int tries = 0; tries < 32; ++tries)
      62                 :         {
      63              20 :             auto const n   = counter.fetch_add(1, std::memory_order_relaxed);
      64              20 :             auto const tag = seed ^ n;
      65                 : 
      66                 :             char buf[32];
      67              20 :             std::snprintf(
      68                 :                 buf, sizeof(buf), "corosio_test_%016llx",
      69                 :                 static_cast<unsigned long long>(tag));
      70                 : 
      71              20 :             auto candidate = base / buf;
      72              20 :             if (fs::create_directory(candidate, ec))
      73                 :             {
      74              20 :                 dir_ = std::move(candidate);
      75              40 :                 return;
      76                 :             }
      77              20 :         }
      78                 :         throw std::runtime_error(
      79 MIS           0 :             "temp_socket_dir: could not create temp directory");
      80 HIT          20 :     }
      81                 : 
      82              20 :     ~temp_socket_dir() noexcept
      83                 :     {
      84              20 :         if (!dir_.empty())
      85                 :         {
      86              20 :             std::error_code ec;
      87              20 :             std::filesystem::remove_all(dir_, ec);
      88                 :         }
      89              20 :     }
      90                 : 
      91                 :     temp_socket_dir(temp_socket_dir const&)            = delete;
      92                 :     temp_socket_dir& operator=(temp_socket_dir const&) = delete;
      93                 : 
      94                 :     /// Path suitable for binding a local socket.
      95              20 :     std::string path() const
      96                 :     {
      97              20 :         return (dir_ / "sock").string();
      98                 :     }
      99                 : 
     100                 : private:
     101                 :     std::filesystem::path dir_;
     102                 : };
     103                 : 
     104                 : } // namespace boost::corosio::test
     105                 : 
     106                 : #endif // BOOST_COROSIO_TEST_TEMP_PATH_HPP
        

Generated by: LCOV version 2.3