1 /* 2 Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 #ifndef _PROCESS_MANAGER_H_ 26 #define _PROCESS_MANAGER_H_ 27 28 #include "process_wrapper.h" 29 30 #include <gmock/gmock.h> 31 #include <chrono> 32 #include <cstring> 33 #include <functional> 34 #include <iostream> 35 #include <list> 36 #include <map> 37 #include <sstream> 38 #include <stdexcept> 39 #include <streambuf> 40 #include <vector> 41 #ifndef _WIN32 42 #include <unistd.h> 43 #endif 44 45 #include "router_test_helpers.h" 46 #include "temp_dir.h" 47 48 using mysql_harness::Path; 49 50 /** @class ProcessManager 51 * 52 * Manages collecion of the processes 53 * Enables creating, shutting down etc. 54 * 55 **/ 56 class ProcessManager { 57 public: 58 /** 59 * set origin path. 60 */ 61 static void set_origin(const Path &dir); 62 63 protected: ~ProcessManager()64 virtual ~ProcessManager() {} 65 66 /** 67 * shutdown all managed processes. 68 */ 69 void shutdown_all(); 70 71 /** 72 * ensures all processes exited and checks for crashes. 73 */ 74 void ensure_clean_exit(); 75 76 /** 77 * ensures given process exited with expected return value and checks for 78 * crashes. 79 */ 80 void check_exit_code( 81 ProcessWrapper &process, int expected_exit_code = EXIT_SUCCESS, 82 std::chrono::milliseconds timeout = kDefaultWaitForExitTimeout); 83 84 void dump_all(); 85 86 /** 87 * ensures given port is ready for accepting connections, prints some debug 88 * data otherwise. 89 * 90 * @param process process that should be listening on that port 91 * @param port TCP port number to check 92 * @param timeout maximum timeout to wait for the port 93 * @param hostname name/IP address of the network host to check 94 */ 95 void check_port_ready( 96 ProcessWrapper &process, uint16_t port, 97 std::chrono::milliseconds timeout = kDefaultPortReadyTimeout, 98 const std::string &hostname = "127.0.0.1"); 99 100 /** 101 * ensures given port is NOT ready for accepting connections, prints some 102 * debug data otherwise. 103 * 104 * @param process process that should be listening on that port 105 * @param port TCP port number to check 106 * @param timeout maximum timeout to wait for the port 107 * @param hostname name/IP address of the network host to check 108 */ 109 void check_port_not_ready( 110 ProcessWrapper &process, uint16_t port, 111 std::chrono::milliseconds timeout = kDefaultPortReadyTimeout, 112 const std::string &hostname = "127.0.0.1"); 113 114 /** @brief Launches the MySQLRouter process. 115 * 116 * @param params vector<string> containing command line parameters to pass 117 * to process 118 * @param expected_exit_code expected exit-code for ensure_clean_exit() 119 * @param catch_stderr bool flag indicating if the process' error output 120 * stream should be included in the output caught from the process 121 * @param with_sudo bool flag indicating if the process' should be 122 * execute with sudo priviledges 123 * 124 * @returns handle to the launched proccess 125 */ 126 ProcessWrapper &launch_router(const std::vector<std::string> ¶ms, 127 int expected_exit_code = 0, 128 bool catch_stderr = true, 129 bool with_sudo = false); 130 131 /** @brief Launches the MySQLServerMock process. 132 * 133 * @param json_file path to the json file containing expected queries 134 * definitions 135 * @param port number of the port where the mock server will accept 136 * the client connections 137 * @param expected_exit_code expected exit-code for ensure_clean_exit() 138 * @param debug_mode if true all the queries and result get printed on the 139 * standard output 140 * @param http_port port number where the http_server module of the mock 141 * server will accept REST client requests 142 * @param x_port port number where the mock server will accept x client 143 * connections 144 * @param module_prefix base-path for javascript modules used by the tests 145 * @param bind_address listen address for the mock server to bind to 146 * 147 * @returns handle to the launched proccess 148 */ 149 ProcessWrapper &launch_mysql_server_mock( 150 const std::string &json_file, unsigned port, int expected_exit_code = 0, 151 bool debug_mode = false, uint16_t http_port = 0, uint16_t x_port = 0, 152 const std::string &module_prefix = "", 153 const std::string &bind_address = "0.0.0.0"); 154 155 /** @brief Launches a process. 156 * 157 * @param command path to executable 158 * @param params array of commanline parameters to pass to the 159 * executable 160 * @param catch_stderr if true stderr will also be captured (combined with 161 * stdout) 162 * 163 * @returns handle to the launched proccess 164 */ 165 ProcessWrapper &launch_command(const std::string &command, 166 const std::vector<std::string> ¶ms, 167 int expected_exit_code = 0, 168 bool catch_stderr = true); 169 170 /** @brief Gets path to the directory containing testing data 171 * (conf files, json files). 172 */ get_data_dir()173 const Path &get_data_dir() const { return data_dir_; } 174 175 /** @brief Gets path to the directory used as log output directory 176 */ get_logging_dir()177 Path get_logging_dir() const { return Path(logging_dir_.name()); } 178 179 /** @brief returns a map with default [DEFAULT] section parameters 180 * 181 * @return default parameters for [DEFAULT] section 182 */ 183 std::map<std::string, std::string> get_DEFAULT_defaults() const; 184 185 /** @brief create config file 186 * 187 * @param directory directory in which the config file will be created 188 * @param sections text to follow [DEFAULT] section (typically all other 189 * sections) 190 * @param default_section [DEFAULT] section parameters 191 * @param name config file name 192 * @param extra_defaults addional parameters to add to [DEFAULT] 193 * @param enable_debug_logging add a logger section with debug level 194 * 195 * @return path to the created file 196 */ 197 std::string create_config_file( 198 const std::string &directory, const std::string §ions = "", 199 const std::map<std::string, std::string> *default_section = nullptr, 200 const std::string &name = "mysqlrouter.conf", 201 const std::string &extra_defaults = "", 202 bool enable_debug_logging = true) const; 203 204 // returns full path to the file 205 std::string create_state_file(const std::string &dir_name, 206 const std::string &content); 207 get_origin()208 static const Path &get_origin() { return origin_dir_; } 209 get_mysqlrouter_exec()210 const Path &get_mysqlrouter_exec() const { return mysqlrouter_exec_; } 211 212 /** 213 * get Path to mysql_server_mock inside the build-dir. 214 * 215 * valid after SetUp() got called. 216 */ get_mysqlserver_mock_exec()217 const Path &get_mysqlserver_mock_exec() const { 218 return mysqlserver_mock_exec_; 219 } 220 set_mysqlrouter_exec(const Path & path)221 void set_mysqlrouter_exec(const Path &path) { mysqlrouter_exec_ = path; } 222 223 protected: 224 /** @brief returns a [DEFAULT] section as string 225 * 226 * @param params map of [DEFAULT] section parameters 227 * @returns [DEFAULT] section text 228 */ 229 std::string make_DEFAULT_section( 230 const std::map<std::string, std::string> *params) const; 231 232 private: 233 void check_port(bool should_be_ready, ProcessWrapper &process, uint16_t port, 234 std::chrono::milliseconds timeout, 235 const std::string &hostname); 236 237 static Path origin_dir_; 238 static Path data_dir_; 239 static Path plugin_dir_; 240 static Path mysqlrouter_exec_; 241 static Path mysqlserver_mock_exec_; 242 243 TempDirectory logging_dir_; 244 245 std::list<std::tuple<ProcessWrapper, int>> processes_; 246 }; 247 248 #endif // _PROCESS_MANAGER_H_ 249