2828#include < sys/socket.h>
2929#include < sys/un.h>
3030#include < stdio.h>
31+ #include < unistd.h>
3132
3233#include < thread>
3334#include < future>
3435#include < chrono>
3536#include < fstream>
37+ #include < cerrno>
38+ #include < cstring>
39+ #include < cstdlib>
40+ #include < vector>
3641
3742#include " swoc/swoc_file.h"
3843
@@ -71,12 +76,75 @@ add_method_handler(const std::string &name, Func &&call)
7176
7277namespace
7378{
74- const std::string sockPath{" tests/var/jsonrpc20_test.sock" };
75- const std::string lockPath{" tests/var/jsonrpc20_test.lock" };
76- constexpr int default_backlog{5 };
77- constexpr int default_maxRetriesOnTransientErrors{64 };
78- constexpr size_t default_incoming_req_max_size{32000 * 3 };
79- DbgCtl dbg_ctl{" rpc.test.client" };
79+ constexpr std::string_view rpc_test_dir_template{" ats_rpc_XXXXXX" };
80+ constexpr std::string_view rpc_test_socket_name{" s" };
81+ constexpr std::string_view rpc_test_lock_name{" l" };
82+ constexpr size_t max_rpc_socket_path_size{sizeof (sockaddr_un::sun_path) - 1 };
83+
84+ fs::path rpcTestDir;
85+ std::string sockPath;
86+ std::string lockPath;
87+ constexpr int default_backlog{5 };
88+ constexpr int default_maxRetriesOnTransientErrors{64 };
89+ constexpr size_t default_incoming_req_max_size{32000 * 3 };
90+ DbgCtl dbg_ctl{" rpc.test.client" };
91+
92+ /* * Prepare JSONRPC socket paths beneath @a base.
93+ *
94+ * This owns creation of the per-run test directory and publishes the socket
95+ * and lock paths shared by the JSONRPC test server and clients.
96+ *
97+ * @param[in] base Candidate parent directory for the test directory.
98+ * @param[out] error Reason setup failed, if a usable directory was not created.
99+ * @return @c true if the socket and lock paths are ready for this test run.
100+ */
101+ bool
102+ try_setup_rpc_test_paths (fs::path const &base, std::string &error)
103+ {
104+ auto const dir_template = (base / rpc_test_dir_template).string ();
105+ auto const socket_path = (fs::path{dir_template} / rpc_test_socket_name).string ();
106+
107+ if (socket_path.size () > max_rpc_socket_path_size) {
108+ error = " JSONRPC test socket path is too long under " + base.string () + " : " + socket_path;
109+ return false ;
110+ }
111+
112+ std::vector<char > mutable_template{dir_template.begin (), dir_template.end ()};
113+ mutable_template.push_back (' \0 ' );
114+
115+ char *created_dir = mkdtemp (mutable_template.data ());
116+ if (created_dir == nullptr ) {
117+ error = " Failed to create JSONRPC test directory under " + base.string () + " : " + std::strerror (errno);
118+ return false ;
119+ }
120+
121+ rpcTestDir = fs::path{created_dir};
122+ sockPath = (rpcTestDir / rpc_test_socket_name).string ();
123+ lockPath = (rpcTestDir / rpc_test_lock_name).string ();
124+ return true ;
125+ }
126+
127+ /* * Prepare JSONRPC socket paths for the test run.
128+ *
129+ * This prefers the environment temporary directory, then falls back to @c /tmp
130+ * when the generated Unix-domain socket path would be too long or setup fails.
131+ *
132+ * @param[out] error Reason setup failed, if no candidate directory works.
133+ * @return @c true if the socket and lock paths are ready for this test run.
134+ */
135+ bool
136+ setup_rpc_test_paths (std::string &error)
137+ {
138+ if (try_setup_rpc_test_paths (fs::temp_directory_path (), error)) {
139+ error.clear ();
140+ return true ;
141+ }
142+ if (try_setup_rpc_test_paths (fs::path{" /tmp" }, error)) {
143+ error.clear ();
144+ return true ;
145+ }
146+ return false ;
147+ }
80148
81149} // end anonymous namespace
82150
@@ -88,6 +156,11 @@ struct RPCServerTestListener : Catch::EventListenerBase {
88156 void
89157 testRunStarting (Catch::TestRunInfo const & /* testRunInfo ATS_UNUSED */ ) override
90158 {
159+ std::string setup_error;
160+ bool const setup_ok = setup_rpc_test_paths (setup_error);
161+ INFO (setup_error);
162+ REQUIRE (setup_ok);
163+
91164 Layout::create ();
92165 init_diags (" rpc" , nullptr );
93166 RecProcessInit ();
@@ -123,6 +196,11 @@ struct RPCServerTestListener : Catch::EventListenerBase {
123196 if (jsonrpcServer) {
124197 delete jsonrpcServer; // will stop the thread
125198 }
199+
200+ std::error_code ec;
201+ if (!rpcTestDir.empty ()) {
202+ fs::remove_all (rpcTestDir, ec);
203+ }
126204 }
127205
128206private:
0 commit comments