- add sources.
[platform/framework/web/crosswalk.git] / src / net / test / embedded_test_server / embedded_test_server_unittest.cc
1 // Copyright (c) 2012 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 #include "net/test/embedded_test_server/embedded_test_server.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "base/threading/thread.h"
9 #include "net/http/http_response_headers.h"
10 #include "net/test/embedded_test_server/http_request.h"
11 #include "net/test/embedded_test_server/http_response.h"
12 #include "net/url_request/url_fetcher.h"
13 #include "net/url_request/url_fetcher_delegate.h"
14 #include "net/url_request/url_request_test_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace net {
18 namespace test_server {
19
20 namespace {
21
22 // Gets the content from the given URLFetcher.
23 std::string GetContentFromFetcher(const URLFetcher& fetcher) {
24   std::string result;
25   const bool success = fetcher.GetResponseAsString(&result);
26   EXPECT_TRUE(success);
27   return result;
28 }
29
30 // Gets the content type from the given URLFetcher.
31 std::string GetContentTypeFromFetcher(const URLFetcher& fetcher) {
32   const HttpResponseHeaders* headers = fetcher.GetResponseHeaders();
33   if (headers) {
34     std::string content_type;
35     if (headers->GetMimeType(&content_type))
36       return content_type;
37   }
38   return std::string();
39 }
40
41 }  // namespace
42
43 class EmbeddedTestServerTest: public testing::Test,
44                               public URLFetcherDelegate {
45  public:
46   EmbeddedTestServerTest()
47       : num_responses_received_(0),
48         num_responses_expected_(0),
49         io_thread_("io_thread") {
50   }
51
52   virtual void SetUp() OVERRIDE {
53     base::Thread::Options thread_options;
54     thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
55     ASSERT_TRUE(io_thread_.StartWithOptions(thread_options));
56
57     request_context_getter_ = new TestURLRequestContextGetter(
58         io_thread_.message_loop_proxy());
59
60     server_.reset(new EmbeddedTestServer);
61     ASSERT_TRUE(server_->InitializeAndWaitUntilReady());
62   }
63
64   virtual void TearDown() OVERRIDE {
65     ASSERT_TRUE(server_->ShutdownAndWaitUntilComplete());
66   }
67
68   // URLFetcherDelegate override.
69   virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE {
70     ++num_responses_received_;
71     if (num_responses_received_ == num_responses_expected_)
72       base::MessageLoop::current()->Quit();
73   }
74
75   // Waits until the specified number of responses are received.
76   void WaitForResponses(int num_responses) {
77     num_responses_received_ = 0;
78     num_responses_expected_ = num_responses;
79     // Will be terminated in OnURLFetchComplete().
80     base::MessageLoop::current()->Run();
81   }
82
83   // Handles |request| sent to |path| and returns the response per |content|,
84   // |content type|, and |code|. Saves the request URL for verification.
85   scoped_ptr<HttpResponse> HandleRequest(const std::string& path,
86                                          const std::string& content,
87                                          const std::string& content_type,
88                                          HttpStatusCode code,
89                                          const HttpRequest& request) {
90     request_relative_url_ = request.relative_url;
91
92     GURL absolute_url = server_->GetURL(request.relative_url);
93     if (absolute_url.path() == path) {
94       scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
95       http_response->set_code(code);
96       http_response->set_content(content);
97       http_response->set_content_type(content_type);
98       return http_response.PassAs<HttpResponse>();
99     }
100
101     return scoped_ptr<HttpResponse>();
102   }
103
104  protected:
105   int num_responses_received_;
106   int num_responses_expected_;
107   std::string request_relative_url_;
108   base::Thread io_thread_;
109   scoped_refptr<TestURLRequestContextGetter> request_context_getter_;
110   scoped_ptr<EmbeddedTestServer> server_;
111 };
112
113 TEST_F(EmbeddedTestServerTest, GetBaseURL) {
114   EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%d/", server_->port()),
115                                server_->base_url().spec());
116 }
117
118 TEST_F(EmbeddedTestServerTest, GetURL) {
119   EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%d/path?query=foo",
120                                server_->port()),
121             server_->GetURL("/path?query=foo").spec());
122 }
123
124 TEST_F(EmbeddedTestServerTest, RegisterRequestHandler) {
125   server_->RegisterRequestHandler(
126       base::Bind(&EmbeddedTestServerTest::HandleRequest,
127                  base::Unretained(this),
128                  "/test",
129                  "<b>Worked!</b>",
130                  "text/html",
131                  HTTP_OK));
132
133   scoped_ptr<URLFetcher> fetcher(
134       URLFetcher::Create(server_->GetURL("/test?q=foo"),
135                               URLFetcher::GET,
136                               this));
137   fetcher->SetRequestContext(request_context_getter_.get());
138   fetcher->Start();
139   WaitForResponses(1);
140
141   EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
142   EXPECT_EQ(HTTP_OK, fetcher->GetResponseCode());
143   EXPECT_EQ("<b>Worked!</b>", GetContentFromFetcher(*fetcher));
144   EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher));
145
146   EXPECT_EQ("/test?q=foo", request_relative_url_);
147 }
148
149 TEST_F(EmbeddedTestServerTest, ServeFilesFromDirectory) {
150   base::FilePath src_dir;
151   ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
152   server_->ServeFilesFromDirectory(
153       src_dir.AppendASCII("net").AppendASCII("data"));
154
155   scoped_ptr<URLFetcher> fetcher(
156       URLFetcher::Create(server_->GetURL("/test.html"),
157                               URLFetcher::GET,
158                               this));
159   fetcher->SetRequestContext(request_context_getter_.get());
160   fetcher->Start();
161   WaitForResponses(1);
162
163   EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
164   EXPECT_EQ(HTTP_OK, fetcher->GetResponseCode());
165   EXPECT_EQ("<p>Hello World!</p>", GetContentFromFetcher(*fetcher));
166   EXPECT_EQ("", GetContentTypeFromFetcher(*fetcher));
167 }
168
169 TEST_F(EmbeddedTestServerTest, DefaultNotFoundResponse) {
170   scoped_ptr<URLFetcher> fetcher(
171       URLFetcher::Create(server_->GetURL("/non-existent"),
172                               URLFetcher::GET,
173                               this));
174   fetcher->SetRequestContext(request_context_getter_.get());
175
176   fetcher->Start();
177   WaitForResponses(1);
178   EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
179   EXPECT_EQ(HTTP_NOT_FOUND, fetcher->GetResponseCode());
180 }
181
182 TEST_F(EmbeddedTestServerTest, ConcurrentFetches) {
183   server_->RegisterRequestHandler(
184       base::Bind(&EmbeddedTestServerTest::HandleRequest,
185                  base::Unretained(this),
186                  "/test1",
187                  "Raspberry chocolate",
188                  "text/html",
189                  HTTP_OK));
190   server_->RegisterRequestHandler(
191       base::Bind(&EmbeddedTestServerTest::HandleRequest,
192                  base::Unretained(this),
193                  "/test2",
194                  "Vanilla chocolate",
195                  "text/html",
196                  HTTP_OK));
197   server_->RegisterRequestHandler(
198       base::Bind(&EmbeddedTestServerTest::HandleRequest,
199                  base::Unretained(this),
200                  "/test3",
201                  "No chocolates",
202                  "text/plain",
203                  HTTP_NOT_FOUND));
204
205   scoped_ptr<URLFetcher> fetcher1 = scoped_ptr<URLFetcher>(
206       URLFetcher::Create(server_->GetURL("/test1"),
207                               URLFetcher::GET,
208                               this));
209   fetcher1->SetRequestContext(request_context_getter_.get());
210   scoped_ptr<URLFetcher> fetcher2 = scoped_ptr<URLFetcher>(
211       URLFetcher::Create(server_->GetURL("/test2"),
212                               URLFetcher::GET,
213                               this));
214   fetcher2->SetRequestContext(request_context_getter_.get());
215   scoped_ptr<URLFetcher> fetcher3 = scoped_ptr<URLFetcher>(
216       URLFetcher::Create(server_->GetURL("/test3"),
217                               URLFetcher::GET,
218                               this));
219   fetcher3->SetRequestContext(request_context_getter_.get());
220
221   // Fetch the three URLs concurrently.
222   fetcher1->Start();
223   fetcher2->Start();
224   fetcher3->Start();
225   WaitForResponses(3);
226
227   EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher1->GetStatus().status());
228   EXPECT_EQ(HTTP_OK, fetcher1->GetResponseCode());
229   EXPECT_EQ("Raspberry chocolate", GetContentFromFetcher(*fetcher1));
230   EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher1));
231
232   EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher2->GetStatus().status());
233   EXPECT_EQ(HTTP_OK, fetcher2->GetResponseCode());
234   EXPECT_EQ("Vanilla chocolate", GetContentFromFetcher(*fetcher2));
235   EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher2));
236
237   EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher3->GetStatus().status());
238   EXPECT_EQ(HTTP_NOT_FOUND, fetcher3->GetResponseCode());
239   EXPECT_EQ("No chocolates", GetContentFromFetcher(*fetcher3));
240   EXPECT_EQ("text/plain", GetContentTypeFromFetcher(*fetcher3));
241 }
242
243 // Below test exercises EmbeddedTestServer's ability to cope with the situation
244 // where there is no MessageLoop available on the thread at EmbeddedTestServer
245 // initialization and/or destruction.
246
247 typedef std::tr1::tuple<bool, bool> ThreadingTestParams;
248
249 class EmbeddedTestServerThreadingTest
250     : public testing::TestWithParam<ThreadingTestParams> {};
251
252 class EmbeddedTestServerThreadingTestDelegate
253     : public base::PlatformThread::Delegate,
254       public URLFetcherDelegate {
255  public:
256   EmbeddedTestServerThreadingTestDelegate(
257       bool message_loop_present_on_initialize,
258       bool message_loop_present_on_shutdown)
259       : message_loop_present_on_initialize_(message_loop_present_on_initialize),
260         message_loop_present_on_shutdown_(message_loop_present_on_shutdown) {}
261
262   // base::PlatformThread::Delegate:
263   virtual void ThreadMain() OVERRIDE {
264     scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner;
265     base::Thread io_thread("io_thread");
266     base::Thread::Options thread_options;
267     thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
268     ASSERT_TRUE(io_thread.StartWithOptions(thread_options));
269     io_thread_runner = io_thread.message_loop_proxy();
270
271     scoped_ptr<base::MessageLoop> loop;
272     if (message_loop_present_on_initialize_)
273       loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
274
275     // Create the test server instance.
276     EmbeddedTestServer server;
277     base::FilePath src_dir;
278     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
279     ASSERT_TRUE(server.InitializeAndWaitUntilReady());
280
281     // Make a request and wait for the reply.
282     if (!loop)
283       loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
284
285     scoped_ptr<URLFetcher> fetcher(URLFetcher::Create(
286         server.GetURL("/test?q=foo"), URLFetcher::GET, this));
287     fetcher->SetRequestContext(
288         new TestURLRequestContextGetter(loop->message_loop_proxy()));
289     fetcher->Start();
290     loop->Run();
291     fetcher.reset();
292
293     // Shut down.
294     if (message_loop_present_on_shutdown_)
295       loop.reset();
296
297     ASSERT_TRUE(server.ShutdownAndWaitUntilComplete());
298   }
299
300   // URLFetcherDelegate override.
301   virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE {
302     base::MessageLoop::current()->Quit();
303   }
304
305  private:
306   bool message_loop_present_on_initialize_;
307   bool message_loop_present_on_shutdown_;
308
309   DISALLOW_COPY_AND_ASSIGN(EmbeddedTestServerThreadingTestDelegate);
310 };
311
312 TEST_P(EmbeddedTestServerThreadingTest, RunTest) {
313   // The actual test runs on a separate thread so it can screw with the presence
314   // of a MessageLoop - the test suite already sets up a MessageLoop for the
315   // main test thread.
316   base::PlatformThreadHandle thread_handle;
317   EmbeddedTestServerThreadingTestDelegate delegate(
318       std::tr1::get<0>(GetParam()),
319       std::tr1::get<1>(GetParam()));
320   ASSERT_TRUE(base::PlatformThread::Create(0, &delegate, &thread_handle));
321   base::PlatformThread::Join(thread_handle);
322 }
323
324 INSTANTIATE_TEST_CASE_P(EmbeddedTestServerThreadingTestInstantiation,
325                         EmbeddedTestServerThreadingTest,
326                         testing::Combine(testing::Bool(), testing::Bool()));
327
328 }  // namespace test_server
329 }  // namespace net