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