Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(729)

Side by Side Diff: chrome_frame/test/test_server.h

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/test/run_all_unittests.cc ('k') | chrome_frame/test/test_server.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CHROME_FRAME_TEST_TEST_SERVER_H_
6 #define CHROME_FRAME_TEST_TEST_SERVER_H_
7
8 // Implementation of an HTTP server for tests.
9 // To instantiate the server, make sure you have a message loop on the
10 // current thread and then create an instance of the SimpleWebServer class.
11 // The server uses two basic concepts, a request and a response.
12 // The Response interface represents an item (e.g. a document) available from
13 // the server. A Request object represents a request from a client (e.g. a
14 // browser). There are several basic Response classes implemented in this file,
15 // all derived from the Response interface.
16 //
17 // Here's a simple example that starts a web server that can serve up
18 // a single document (http://localhost:1337/foo).
19 // All other requests will get a 404.
20 //
21 // MessageLoopForUI loop;
22 // test_server::SimpleWebServer server(1337);
23 // test_server::SimpleResponse document("/foo", "Hello World!");
24 // test_server.AddResponse(&document);
25 // loop.MessageLoop::Run();
26 //
27 // To close the web server, just go to http://localhost:1337/quit.
28 //
29 // All Response classes count how many times they have been accessed. Just
30 // call Response::accessed().
31 //
32 // To implement a custom response object (e.g. to match against a request
33 // based on some data, serve up dynamic content or take some action on the
34 // server), just inherit from one of the response classes or directly from the
35 // Response interface and add your response object to the server's list of
36 // response objects.
37
38 #include <list>
39 #include <string>
40
41 #include "base/basictypes.h"
42 #include "base/file_util.h"
43 #include "net/base/listen_socket.h"
44
45 namespace test_server {
46
47 class Request {
48 public:
49 Request() : content_length_(0) {
50 }
51
52 void ParseHeaders(const std::string& headers);
53
54 const std::string& method() const {
55 return method_;
56 }
57
58 const std::string& path() const {
59 return path_;
60 }
61
62 const std::string& headers() const {
63 return headers_;
64 }
65
66 size_t content_length() const {
67 return content_length_;
68 }
69
70 protected:
71 std::string method_;
72 std::string path_;
73 std::string version_;
74 std::string headers_;
75 size_t content_length_;
76
77 private:
78 DISALLOW_COPY_AND_ASSIGN(Request);
79 };
80
81 // Manages request headers for a single request.
82 // For each successful request that's made, the server will keep an instance
83 // of this class so that they can be checked even after the server has been
84 // shut down.
85 class Connection {
86 public:
87 explicit Connection(ListenSocket* sock) : socket_(sock) {
88 }
89
90 ~Connection() {
91 }
92
93 bool IsSame(const ListenSocket* socket) const {
94 return socket_ == socket;
95 }
96
97 void AddData(const std::string& data) {
98 data_ += data;
99 }
100
101 bool CheckRequestReceived();
102
103 const Request& request() const {
104 return request_;
105 }
106
107 protected:
108 scoped_refptr<ListenSocket> socket_;
109 std::string data_;
110 Request request_;
111
112 private:
113 DISALLOW_COPY_AND_ASSIGN(Connection);
114 };
115
116 // Abstract interface with default implementations for some of the methods and
117 // a counter for how many times the response object has served requests.
118 class Response {
119 public:
120 Response() : accessed_(0) {
121 }
122
123 virtual ~Response() {
124 }
125
126 // Returns true if this response object should be used for a given request.
127 virtual bool Matches(const Request& r) const = 0;
128
129 // Response objects can optionally supply their own HTTP headers, completely
130 // bypassing the default ones.
131 virtual bool GetCustomHeaders(std::string* headers) const {
132 return false;
133 }
134
135 // Optionally provide a content type. Return false if you don't specify
136 // a content type.
137 virtual bool GetContentType(std::string* content_type) const {
138 return false;
139 }
140
141 virtual size_t ContentLength() const {
142 return 0;
143 }
144
145 virtual void WriteContents(ListenSocket* socket) const {
146 }
147
148 void IncrementAccessCounter() {
149 accessed_++;
150 }
151
152 size_t accessed() const {
153 return accessed_;
154 }
155
156 protected:
157 size_t accessed_;
158
159 private:
160 DISALLOW_COPY_AND_ASSIGN(Response);
161 };
162
163 // Partial implementation of Response that matches a request's path.
164 // This is just a convenience implementation for the boilerplate implementation
165 // of Matches(). Don't instantiate directly.
166 class ResponseForPath : public Response {
167 public:
168 explicit ResponseForPath(const char* request_path)
169 : request_path_(request_path) {
170 }
171
172 virtual bool Matches(const Request& r) const {
173 return r.path().compare(request_path_) == 0;
174 }
175
176 protected:
177 std::string request_path_;
178
179 private:
180 DISALLOW_COPY_AND_ASSIGN(ResponseForPath);
181 };
182
183 // A very basic implementation of a response.
184 // A simple response matches a single document path on the server
185 // (e.g. "/foo") and returns a document in the form of a string.
186 class SimpleResponse : public ResponseForPath {
187 public:
188 SimpleResponse(const char* request_path, const std::string& contents)
189 : ResponseForPath(request_path), contents_(contents) {
190 }
191
192 virtual void WriteContents(ListenSocket* socket) const {
193 socket->Send(contents_.c_str(), contents_.length(), false);
194 }
195
196 virtual size_t ContentLength() const {
197 return contents_.length();
198 }
199
200 protected:
201 std::string contents_;
202
203 private:
204 DISALLOW_COPY_AND_ASSIGN(SimpleResponse);
205 };
206
207 // To serve up files from the web server, create an instance of FileResponse
208 // and add it to the server's list of responses. The content type of the
209 // file will be determined by calling FindMimeFromData which examines the
210 // contents of the file and performs registry lookups.
211 class FileResponse : public ResponseForPath {
212 public:
213 FileResponse(const char* request_path, const FilePath& file_path)
214 : ResponseForPath(request_path), file_path_(file_path) {
215 }
216
217 virtual bool GetContentType(std::string* content_type) const;
218 virtual void WriteContents(ListenSocket* socket) const;
219 virtual size_t ContentLength() const;
220
221 protected:
222 FilePath file_path_;
223 mutable scoped_ptr<file_util::MemoryMappedFile> file_;
224
225 private:
226 DISALLOW_COPY_AND_ASSIGN(FileResponse);
227 };
228
229 // Returns a 302 (temporary redirect) to redirect the client from a path
230 // on the test server to a different URL.
231 class RedirectResponse : public ResponseForPath {
232 public:
233 RedirectResponse(const char* request_path, const std::string& redirect_url)
234 : ResponseForPath(request_path), redirect_url_(redirect_url) {
235 }
236
237 virtual bool GetCustomHeaders(std::string* headers) const;
238
239 protected:
240 std::string redirect_url_;
241
242 private:
243 DISALLOW_COPY_AND_ASSIGN(RedirectResponse);
244 };
245
246 // typedef for a list of connections. Used by SimpleWebServer.
247 typedef std::list<Connection*> ConnectionList;
248
249 // Implementation of a simple http server.
250 // Before creating an instance of the server, make sure the current thread
251 // has a message loop.
252 class SimpleWebServer : public ListenSocket::ListenSocketDelegate {
253 public:
254 explicit SimpleWebServer(int port);
255 virtual ~SimpleWebServer();
256
257 void AddResponse(Response* response);
258
259 // ListenSocketDelegate overrides.
260 virtual void DidAccept(ListenSocket* server, ListenSocket* connection);
261 virtual void DidRead(ListenSocket* connection, const std::string& data);
262 virtual void DidClose(ListenSocket* sock);
263
264 const ConnectionList& connections() {
265 return connections_;
266 }
267
268 protected:
269 class QuitResponse : public SimpleResponse {
270 public:
271 QuitResponse()
272 : SimpleResponse("/quit", "So long and thanks for all the fish.") {
273 }
274
275 virtual void QuitResponse::WriteContents(ListenSocket* socket) const {
276 SimpleResponse::WriteContents(socket);
277 MessageLoop::current()->Quit();
278 }
279 };
280
281 Response* FindResponse(const Request& request) const;
282 Connection* FindConnection(const ListenSocket* socket) const;
283
284 protected:
285 scoped_refptr<ListenSocket> server_;
286 ConnectionList connections_;
287 std::list<Response*> responses_;
288 QuitResponse quit_;
289
290 private:
291 DISALLOW_COPY_AND_ASSIGN(SimpleWebServer);
292 };
293
294 } // namespace test_server
295
296 #endif // CHROME_FRAME_TEST_TEST_SERVER_H_
OLDNEW
« no previous file with comments | « chrome_frame/test/run_all_unittests.cc ('k') | chrome_frame/test/test_server.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698