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.
5 #include "net/test/embedded_test_server/embedded_test_server.h"
7 #include "base/path_service.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/threading/thread.h"
11 #include "net/http/http_response_headers.h"
12 #include "net/test/embedded_test_server/http_request.h"
13 #include "net/test/embedded_test_server/http_response.h"
14 #include "net/url_request/url_fetcher.h"
15 #include "net/url_request/url_fetcher_delegate.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gtest/include/gtest/gtest.h"
20 namespace test_server
{
24 // Gets the content from the given URLFetcher.
25 std::string
GetContentFromFetcher(const URLFetcher
& fetcher
) {
27 const bool success
= fetcher
.GetResponseAsString(&result
);
32 // Gets the content type from the given URLFetcher.
33 std::string
GetContentTypeFromFetcher(const URLFetcher
& fetcher
) {
34 const HttpResponseHeaders
* headers
= fetcher
.GetResponseHeaders();
36 std::string content_type
;
37 if (headers
->GetMimeType(&content_type
))
45 class EmbeddedTestServerTest
: public testing::Test
,
46 public URLFetcherDelegate
{
48 EmbeddedTestServerTest()
49 : num_responses_received_(0),
50 num_responses_expected_(0),
51 io_thread_("io_thread") {
54 void SetUp() override
{
55 base::Thread::Options thread_options
;
56 thread_options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
57 ASSERT_TRUE(io_thread_
.StartWithOptions(thread_options
));
59 request_context_getter_
=
60 new TestURLRequestContextGetter(io_thread_
.task_runner());
62 server_
.reset(new EmbeddedTestServer
);
63 ASSERT_TRUE(server_
->InitializeAndWaitUntilReady());
66 void TearDown() override
{
67 ASSERT_TRUE(server_
->ShutdownAndWaitUntilComplete());
70 // URLFetcherDelegate override.
71 void OnURLFetchComplete(const URLFetcher
* source
) override
{
72 ++num_responses_received_
;
73 if (num_responses_received_
== num_responses_expected_
)
74 base::MessageLoop::current()->Quit();
77 // Waits until the specified number of responses are received.
78 void WaitForResponses(int num_responses
) {
79 num_responses_received_
= 0;
80 num_responses_expected_
= num_responses
;
81 // Will be terminated in OnURLFetchComplete().
82 base::MessageLoop::current()->Run();
85 // Handles |request| sent to |path| and returns the response per |content|,
86 // |content type|, and |code|. Saves the request URL for verification.
87 scoped_ptr
<HttpResponse
> HandleRequest(const std::string
& path
,
88 const std::string
& content
,
89 const std::string
& content_type
,
91 const HttpRequest
& request
) {
92 request_relative_url_
= request
.relative_url
;
94 GURL absolute_url
= server_
->GetURL(request
.relative_url
);
95 if (absolute_url
.path() == path
) {
96 scoped_ptr
<BasicHttpResponse
> http_response(new BasicHttpResponse
);
97 http_response
->set_code(code
);
98 http_response
->set_content(content
);
99 http_response
->set_content_type(content_type
);
100 return http_response
.Pass();
107 int num_responses_received_
;
108 int num_responses_expected_
;
109 std::string request_relative_url_
;
110 base::Thread io_thread_
;
111 scoped_refptr
<TestURLRequestContextGetter
> request_context_getter_
;
112 scoped_ptr
<EmbeddedTestServer
> server_
;
115 TEST_F(EmbeddedTestServerTest
, GetBaseURL
) {
116 EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%u/", server_
->port()),
117 server_
->base_url().spec());
120 TEST_F(EmbeddedTestServerTest
, GetURL
) {
121 EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%u/path?query=foo",
123 server_
->GetURL("/path?query=foo").spec());
126 TEST_F(EmbeddedTestServerTest
, GetURLWithHostname
) {
127 EXPECT_EQ(base::StringPrintf("http://foo.com:%d/path?query=foo",
129 server_
->GetURL("foo.com", "/path?query=foo").spec());
132 TEST_F(EmbeddedTestServerTest
, RegisterRequestHandler
) {
133 server_
->RegisterRequestHandler(
134 base::Bind(&EmbeddedTestServerTest::HandleRequest
,
135 base::Unretained(this),
141 scoped_ptr
<URLFetcher
> fetcher
=
142 URLFetcher::Create(server_
->GetURL("/test?q=foo"), URLFetcher::GET
, this);
143 fetcher
->SetRequestContext(request_context_getter_
.get());
147 EXPECT_EQ(URLRequestStatus::SUCCESS
, fetcher
->GetStatus().status());
148 EXPECT_EQ(HTTP_OK
, fetcher
->GetResponseCode());
149 EXPECT_EQ("<b>Worked!</b>", GetContentFromFetcher(*fetcher
));
150 EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher
));
152 EXPECT_EQ("/test?q=foo", request_relative_url_
);
155 TEST_F(EmbeddedTestServerTest
, ServeFilesFromDirectory
) {
156 base::FilePath src_dir
;
157 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &src_dir
));
158 server_
->ServeFilesFromDirectory(
159 src_dir
.AppendASCII("net").AppendASCII("data"));
161 scoped_ptr
<URLFetcher
> fetcher
=
162 URLFetcher::Create(server_
->GetURL("/test.html"), URLFetcher::GET
, this);
163 fetcher
->SetRequestContext(request_context_getter_
.get());
167 EXPECT_EQ(URLRequestStatus::SUCCESS
, fetcher
->GetStatus().status());
168 EXPECT_EQ(HTTP_OK
, fetcher
->GetResponseCode());
169 EXPECT_EQ("<p>Hello World!</p>", GetContentFromFetcher(*fetcher
));
170 EXPECT_EQ("", GetContentTypeFromFetcher(*fetcher
));
173 TEST_F(EmbeddedTestServerTest
, DefaultNotFoundResponse
) {
174 scoped_ptr
<URLFetcher
> fetcher
= URLFetcher::Create(
175 server_
->GetURL("/non-existent"), URLFetcher::GET
, this);
176 fetcher
->SetRequestContext(request_context_getter_
.get());
180 EXPECT_EQ(URLRequestStatus::SUCCESS
, fetcher
->GetStatus().status());
181 EXPECT_EQ(HTTP_NOT_FOUND
, fetcher
->GetResponseCode());
184 TEST_F(EmbeddedTestServerTest
, ConcurrentFetches
) {
185 server_
->RegisterRequestHandler(
186 base::Bind(&EmbeddedTestServerTest::HandleRequest
,
187 base::Unretained(this),
189 "Raspberry chocolate",
192 server_
->RegisterRequestHandler(
193 base::Bind(&EmbeddedTestServerTest::HandleRequest
,
194 base::Unretained(this),
199 server_
->RegisterRequestHandler(
200 base::Bind(&EmbeddedTestServerTest::HandleRequest
,
201 base::Unretained(this),
207 scoped_ptr
<URLFetcher
> fetcher1
=
208 URLFetcher::Create(server_
->GetURL("/test1"), URLFetcher::GET
, this);
209 fetcher1
->SetRequestContext(request_context_getter_
.get());
210 scoped_ptr
<URLFetcher
> fetcher2
=
211 URLFetcher::Create(server_
->GetURL("/test2"), URLFetcher::GET
, this);
212 fetcher2
->SetRequestContext(request_context_getter_
.get());
213 scoped_ptr
<URLFetcher
> fetcher3
=
214 URLFetcher::Create(server_
->GetURL("/test3"), URLFetcher::GET
, this);
215 fetcher3
->SetRequestContext(request_context_getter_
.get());
217 // Fetch the three URLs concurrently.
223 EXPECT_EQ(URLRequestStatus::SUCCESS
, fetcher1
->GetStatus().status());
224 EXPECT_EQ(HTTP_OK
, fetcher1
->GetResponseCode());
225 EXPECT_EQ("Raspberry chocolate", GetContentFromFetcher(*fetcher1
));
226 EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher1
));
228 EXPECT_EQ(URLRequestStatus::SUCCESS
, fetcher2
->GetStatus().status());
229 EXPECT_EQ(HTTP_OK
, fetcher2
->GetResponseCode());
230 EXPECT_EQ("Vanilla chocolate", GetContentFromFetcher(*fetcher2
));
231 EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher2
));
233 EXPECT_EQ(URLRequestStatus::SUCCESS
, fetcher3
->GetStatus().status());
234 EXPECT_EQ(HTTP_NOT_FOUND
, fetcher3
->GetResponseCode());
235 EXPECT_EQ("No chocolates", GetContentFromFetcher(*fetcher3
));
236 EXPECT_EQ("text/plain", GetContentTypeFromFetcher(*fetcher3
));
239 // Below test exercises EmbeddedTestServer's ability to cope with the situation
240 // where there is no MessageLoop available on the thread at EmbeddedTestServer
241 // initialization and/or destruction.
243 typedef std::tr1::tuple
<bool, bool> ThreadingTestParams
;
245 class EmbeddedTestServerThreadingTest
246 : public testing::TestWithParam
<ThreadingTestParams
> {};
248 class EmbeddedTestServerThreadingTestDelegate
249 : public base::PlatformThread::Delegate
,
250 public URLFetcherDelegate
{
252 EmbeddedTestServerThreadingTestDelegate(
253 bool message_loop_present_on_initialize
,
254 bool message_loop_present_on_shutdown
)
255 : message_loop_present_on_initialize_(message_loop_present_on_initialize
),
256 message_loop_present_on_shutdown_(message_loop_present_on_shutdown
) {}
258 // base::PlatformThread::Delegate:
259 void ThreadMain() override
{
260 scoped_refptr
<base::SingleThreadTaskRunner
> io_thread_runner
;
261 base::Thread
io_thread("io_thread");
262 base::Thread::Options thread_options
;
263 thread_options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
264 ASSERT_TRUE(io_thread
.StartWithOptions(thread_options
));
265 io_thread_runner
= io_thread
.task_runner();
267 scoped_ptr
<base::MessageLoop
> loop
;
268 if (message_loop_present_on_initialize_
)
269 loop
.reset(new base::MessageLoopForIO
);
271 // Create the test server instance.
272 EmbeddedTestServer server
;
273 base::FilePath src_dir
;
274 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &src_dir
));
275 ASSERT_TRUE(server
.InitializeAndWaitUntilReady());
277 // Make a request and wait for the reply.
279 loop
.reset(new base::MessageLoopForIO
);
281 scoped_ptr
<URLFetcher
> fetcher
=
282 URLFetcher::Create(server
.GetURL("/test?q=foo"), URLFetcher::GET
, this);
283 fetcher
->SetRequestContext(
284 new TestURLRequestContextGetter(loop
->task_runner()));
290 if (message_loop_present_on_shutdown_
)
293 ASSERT_TRUE(server
.ShutdownAndWaitUntilComplete());
296 // URLFetcherDelegate override.
297 void OnURLFetchComplete(const URLFetcher
* source
) override
{
298 base::MessageLoop::current()->Quit();
302 bool message_loop_present_on_initialize_
;
303 bool message_loop_present_on_shutdown_
;
305 DISALLOW_COPY_AND_ASSIGN(EmbeddedTestServerThreadingTestDelegate
);
308 TEST_P(EmbeddedTestServerThreadingTest
, RunTest
) {
309 // The actual test runs on a separate thread so it can screw with the presence
310 // of a MessageLoop - the test suite already sets up a MessageLoop for the
312 base::PlatformThreadHandle thread_handle
;
313 EmbeddedTestServerThreadingTestDelegate
delegate(
314 std::tr1::get
<0>(GetParam()),
315 std::tr1::get
<1>(GetParam()));
316 ASSERT_TRUE(base::PlatformThread::Create(0, &delegate
, &thread_handle
));
317 base::PlatformThread::Join(thread_handle
);
320 INSTANTIATE_TEST_CASE_P(EmbeddedTestServerThreadingTestInstantiation
,
321 EmbeddedTestServerThreadingTest
,
322 testing::Combine(testing::Bool(), testing::Bool()));
324 } // namespace test_server