xref: /aosp_15_r20/external/cronet/net/test/spawned_test_server/base_test_server.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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