1 // Copyright 2013 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // NOTE: spawned_test_server is deprecated, since it frequently causes test 6 // flakiness. Please consider using embedded_test_server if possible. 7 8 #ifndef NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_ 9 #define NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_ 10 11 #include <stdint.h> 12 13 #include <memory> 14 #include <optional> 15 #include <string> 16 #include <utility> 17 #include <vector> 18 19 #include "base/files/file_path.h" 20 #include "base/memory/scoped_refptr.h" 21 #include "base/values.h" 22 #include "net/base/host_port_pair.h" 23 #include "net/cert/test_root_certs.h" 24 25 class GURL; 26 27 namespace net { 28 29 class AddressList; 30 class ScopedPortException; 31 class ScopedTestRoot; 32 class X509Certificate; 33 34 // The base class of Test server implementation. 35 class BaseTestServer { 36 public: 37 typedef std::pair<std::string, std::string> StringPair; 38 39 enum Type { 40 TYPE_BASIC_AUTH_PROXY, 41 TYPE_WS, 42 TYPE_WSS, 43 TYPE_PROXY, 44 }; 45 46 // Container for various options to control how the HTTPS or WSS server is 47 // initialized. 48 struct SSLOptions { 49 enum ServerCertificate { 50 CERT_OK, 51 52 CERT_MISMATCHED_NAME, 53 CERT_EXPIRED, 54 // Cross-signed certificate to test PKIX path building. Contains an 55 // intermediate cross-signed by an unknown root, while the client (via 56 // TestRootStore) is expected to have a self-signed version of the 57 // intermediate. 58 CERT_CHAIN_WRONG_ROOT, 59 60 // Causes the testserver to use a hostname that is a domain 61 // instead of an IP. 62 CERT_COMMON_NAME_IS_DOMAIN, 63 64 // An RSA certificate with the keyUsage extension specifying that the key 65 // is only for encipherment. 66 CERT_KEY_USAGE_RSA_ENCIPHERMENT, 67 68 // An RSA certificate with the keyUsage extension specifying that the key 69 // is only for digital signatures. 70 CERT_KEY_USAGE_RSA_DIGITAL_SIGNATURE, 71 72 // A certificate with invalid notBefore and notAfter times. Windows' 73 // certificate library will not parse this certificate. 74 CERT_BAD_VALIDITY, 75 76 // A certificate that covers a number of test names. See [test_names] in 77 // net/data/ssl/scripts/ee.cnf. More may be added by editing this list and 78 // and rerunning net/data/ssl/scripts/generate-test-certs.sh. 79 CERT_TEST_NAMES, 80 }; 81 82 // Initialize a new SSLOptions using CERT_OK as the certificate. 83 SSLOptions(); 84 85 // Initialize a new SSLOptions that will use the specified certificate. 86 explicit SSLOptions(ServerCertificate cert); 87 explicit SSLOptions(base::FilePath cert); 88 SSLOptions(const SSLOptions& other); 89 ~SSLOptions(); 90 91 // Returns the relative filename of the file that contains the 92 // |server_certificate|. 93 base::FilePath GetCertificateFile() const; 94 95 // The certificate to use when serving requests. 96 ServerCertificate server_certificate = CERT_OK; 97 base::FilePath custom_certificate; 98 99 // True if a CertificateRequest should be sent to the client during 100 // handshaking. 101 bool request_client_certificate = false; 102 103 // If |request_client_certificate| is true, an optional list of files, 104 // each containing a single, PEM-encoded X.509 certificates. The subject 105 // from each certificate will be added to the certificate_authorities 106 // field of the CertificateRequest. 107 std::vector<base::FilePath> client_authorities; 108 }; 109 110 // Initialize a TestServer. 111 explicit BaseTestServer(Type type); 112 113 // Initialize a TestServer with a specific set of SSLOptions for HTTPS or WSS. 114 BaseTestServer(Type type, const SSLOptions& ssl_options); 115 116 BaseTestServer(const BaseTestServer&) = delete; 117 BaseTestServer& operator=(const BaseTestServer&) = delete; 118 119 // Starts the server blocking until the server is ready. 120 [[nodiscard]] bool Start(); 121 122 // Start the test server without blocking. Use this if you need multiple test 123 // servers (such as WebSockets and HTTP, or HTTP and HTTPS). You must call 124 // BlockUntilStarted on all servers your test requires before executing the 125 // test. For example: 126 // 127 // // Start the servers in parallel. 128 // ASSERT_TRUE(http_server.StartInBackground()); 129 // ASSERT_TRUE(websocket_server.StartInBackground()); 130 // // Wait for both servers to be ready. 131 // ASSERT_TRUE(http_server.BlockUntilStarted()); 132 // ASSERT_TRUE(websocket_server.BlockUntilStarted()); 133 // RunMyTest(); 134 // 135 // Returns true on success. 136 [[nodiscard]] virtual bool StartInBackground() = 0; 137 138 // Block until the test server is ready. Returns true on success. See 139 // StartInBackground() documentation for more information. 140 [[nodiscard]] virtual bool BlockUntilStarted() = 0; 141 142 // Returns the host port pair used by current Python based test server only 143 // if the server is started. 144 const HostPortPair& host_port_pair() const; 145 document_root()146 const base::FilePath& document_root() const { return document_root_; } 147 std::string GetScheme() const; 148 [[nodiscard]] bool GetAddressList(AddressList* address_list) const; 149 150 GURL GetURL(const std::string& path) const; 151 GURL GetURL(const std::string& hostname, 152 const std::string& relative_url) const; 153 154 GURL GetURLWithUser(const std::string& path, 155 const std::string& user) const; 156 157 GURL GetURLWithUserAndPassword(const std::string& path, 158 const std::string& user, 159 const std::string& password) const; 160 161 static bool GetFilePathWithReplacements( 162 const std::string& original_path, 163 const std::vector<StringPair>& text_to_replace, 164 std::string* replacement_path); 165 UsingSSL(Type type)166 static bool UsingSSL(Type type) { return type == BaseTestServer::TYPE_WSS; } 167 168 // Enable HTTP basic authentication. Currently this only works for TYPE_WS and 169 // TYPE_WSS. set_websocket_basic_auth(bool ws_basic_auth)170 void set_websocket_basic_auth(bool ws_basic_auth) { 171 ws_basic_auth_ = ws_basic_auth; 172 } 173 174 // Redirect proxied CONNECT requests to localhost. set_redirect_connect_to_localhost(bool redirect_connect_to_localhost)175 void set_redirect_connect_to_localhost(bool redirect_connect_to_localhost) { 176 redirect_connect_to_localhost_ = redirect_connect_to_localhost; 177 } 178 179 // Registers the test server's certs for the current process. 180 [[nodiscard]] static ScopedTestRoot RegisterTestCerts(); 181 182 // Marks the root certificate of an HTTPS test server as trusted for 183 // the duration of tests. 184 [[nodiscard]] bool LoadTestRootCert(); 185 186 // Returns the certificate that the server is using. 187 scoped_refptr<X509Certificate> GetCertificate() const; 188 189 protected: 190 virtual ~BaseTestServer(); type()191 Type type() const { return type_; } ssl_options()192 const SSLOptions& ssl_options() const { return ssl_options_; } 193 started()194 bool started() const { return started_; } 195 196 // Gets port currently assigned to host_port_pair_ without checking 197 // whether it's available (server started) or not. 198 uint16_t GetPort(); 199 200 // Sets |port| as the actual port used by Python based test server. 201 void SetPort(uint16_t port); 202 203 // Set up internal status when the server is started. 204 [[nodiscard]] bool SetupWhenServerStarted(); 205 206 // Clean up internal status when starting to stop server. 207 void CleanUpWhenStoppingServer(); 208 209 // Set path of test resources. 210 void SetResourcePath(const base::FilePath& document_root, 211 const base::FilePath& certificates_dir); 212 213 // Parses the server data read from the test server and sets |server_data_|. 214 // *port is set to the port number specified in server_data. The port may be 215 // different from the local port set in |host_port_pair_|, specifically when 216 // using RemoteTestServer (which proxies connections from 127.0.0.1 to a 217 // different IP). Returns true on success. 218 [[nodiscard]] bool SetAndParseServerData(const std::string& server_data, 219 int* port); 220 221 // Returns a base::Value::Dict with the arguments for launching the external 222 // Python test server, in the form of 223 // { argument-name: argument-value, ... } 224 // 225 // Returns nullopt if an invalid configuration is specified. 226 std::optional<base::Value::Dict> GenerateArguments() const; 227 228 private: 229 void Init(const std::string& host); 230 231 // Document root of the test server. 232 base::FilePath document_root_; 233 234 // Directory that contains the SSL certificates. 235 base::FilePath certificates_dir_; 236 237 ScopedTestRoot scoped_test_root_; 238 239 // Address on which the tests should connect to the server. With 240 // RemoteTestServer it may be different from the address on which the server 241 // listens on. 242 HostPortPair host_port_pair_; 243 244 // If |UsingSSL(type_)|, the TLS settings to use for the test server. 245 SSLOptions ssl_options_; 246 247 Type type_; 248 249 // Has the server been started? 250 bool started_ = false; 251 252 // Enables logging of the server to the console. 253 bool log_to_console_ = false; 254 255 // Is WebSocket basic HTTP authentication enabled? 256 bool ws_basic_auth_ = false; 257 258 // Redirect proxied CONNECT requests to localhost? 259 bool redirect_connect_to_localhost_ = false; 260 261 std::unique_ptr<ScopedPortException> allowed_port_; 262 }; 263 264 } // namespace net 265 266 #endif // NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_ 267