Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / test / embedded_test_server / embedded_test_server_unittest.cc
blob4ff1afc38a14fcab3b07b8a234a5ab310fedc0a1
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/run_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/synchronization/lock.h"
12 #include "base/threading/thread.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/log/test_net_log.h"
16 #include "net/socket/client_socket_factory.h"
17 #include "net/socket/stream_socket.h"
18 #include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
19 #include "net/test/embedded_test_server/http_request.h"
20 #include "net/test/embedded_test_server/http_response.h"
21 #include "net/test/spawned_test_server/base_test_server.h"
22 #include "net/url_request/url_fetcher.h"
23 #include "net/url_request/url_fetcher_delegate.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 namespace net {
28 namespace test_server {
30 namespace {
32 // Gets the content from the given URLFetcher.
33 std::string GetContentFromFetcher(const URLFetcher& fetcher) {
34 std::string result;
35 const bool success = fetcher.GetResponseAsString(&result);
36 EXPECT_TRUE(success);
37 return result;
40 // Gets the content type from the given URLFetcher.
41 std::string GetContentTypeFromFetcher(const URLFetcher& fetcher) {
42 const HttpResponseHeaders* headers = fetcher.GetResponseHeaders();
43 if (headers) {
44 std::string content_type;
45 if (headers->GetMimeType(&content_type))
46 return content_type;
48 return std::string();
51 } // namespace
53 // Gets notified by the EmbeddedTestServer on incoming connections being
54 // accepted, read from, or closed.
55 class TestConnectionListener
56 : public net::test_server::EmbeddedTestServerConnectionListener {
57 public:
58 TestConnectionListener()
59 : socket_accepted_count_(0),
60 did_read_from_socket_(false),
61 task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
63 ~TestConnectionListener() override {}
65 // Get called from the EmbeddedTestServer thread to be notified that
66 // a connection was accepted.
67 void AcceptedSocket(
68 const net::test_server::StreamListenSocket& connection) override {
69 base::AutoLock lock(lock_);
70 ++socket_accepted_count_;
71 task_runner_->PostTask(FROM_HERE, accept_loop_.QuitClosure());
74 // Get called from the EmbeddedTestServer thread to be notified that
75 // a connection was read from.
76 void ReadFromSocket(
77 const net::test_server::StreamListenSocket& connection) override {
78 base::AutoLock lock(lock_);
79 did_read_from_socket_ = true;
82 void WaitUntilFirstConnectionAccepted() { accept_loop_.Run(); }
84 size_t SocketAcceptedCount() const {
85 base::AutoLock lock(lock_);
86 return socket_accepted_count_;
89 bool DidReadFromSocket() const {
90 base::AutoLock lock(lock_);
91 return did_read_from_socket_;
94 private:
95 size_t socket_accepted_count_;
96 bool did_read_from_socket_;
98 base::RunLoop accept_loop_;
99 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
101 mutable base::Lock lock_;
103 DISALLOW_COPY_AND_ASSIGN(TestConnectionListener);
106 class EmbeddedTestServerTest: public testing::Test,
107 public URLFetcherDelegate {
108 public:
109 EmbeddedTestServerTest()
110 : num_responses_received_(0),
111 num_responses_expected_(0),
112 io_thread_("io_thread") {
115 void SetUp() override {
116 base::Thread::Options thread_options;
117 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
118 ASSERT_TRUE(io_thread_.StartWithOptions(thread_options));
120 request_context_getter_ =
121 new TestURLRequestContextGetter(io_thread_.task_runner());
123 server_.reset(new EmbeddedTestServer);
124 server_->SetConnectionListener(&connection_listener_);
125 ASSERT_TRUE(server_->InitializeAndWaitUntilReady());
128 void TearDown() override {
129 ASSERT_TRUE(server_->ShutdownAndWaitUntilComplete());
132 // URLFetcherDelegate override.
133 void OnURLFetchComplete(const URLFetcher* source) override {
134 ++num_responses_received_;
135 if (num_responses_received_ == num_responses_expected_)
136 base::MessageLoop::current()->Quit();
139 // Waits until the specified number of responses are received.
140 void WaitForResponses(int num_responses) {
141 num_responses_received_ = 0;
142 num_responses_expected_ = num_responses;
143 // Will be terminated in OnURLFetchComplete().
144 base::MessageLoop::current()->Run();
147 // Handles |request| sent to |path| and returns the response per |content|,
148 // |content type|, and |code|. Saves the request URL for verification.
149 scoped_ptr<HttpResponse> HandleRequest(const std::string& path,
150 const std::string& content,
151 const std::string& content_type,
152 HttpStatusCode code,
153 const HttpRequest& request) {
154 request_relative_url_ = request.relative_url;
156 GURL absolute_url = server_->GetURL(request.relative_url);
157 if (absolute_url.path() == path) {
158 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
159 http_response->set_code(code);
160 http_response->set_content(content);
161 http_response->set_content_type(content_type);
162 return http_response.Pass();
165 return nullptr;
168 protected:
169 int num_responses_received_;
170 int num_responses_expected_;
171 std::string request_relative_url_;
172 base::Thread io_thread_;
173 scoped_refptr<TestURLRequestContextGetter> request_context_getter_;
174 TestConnectionListener connection_listener_;
175 scoped_ptr<EmbeddedTestServer> server_;
178 TEST_F(EmbeddedTestServerTest, GetBaseURL) {
179 EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%u/", server_->port()),
180 server_->base_url().spec());
183 TEST_F(EmbeddedTestServerTest, GetURL) {
184 EXPECT_EQ(base::StringPrintf("http://127.0.0.1:%u/path?query=foo",
185 server_->port()),
186 server_->GetURL("/path?query=foo").spec());
189 TEST_F(EmbeddedTestServerTest, GetURLWithHostname) {
190 EXPECT_EQ(base::StringPrintf("http://foo.com:%d/path?query=foo",
191 server_->port()),
192 server_->GetURL("foo.com", "/path?query=foo").spec());
195 TEST_F(EmbeddedTestServerTest, RegisterRequestHandler) {
196 server_->RegisterRequestHandler(
197 base::Bind(&EmbeddedTestServerTest::HandleRequest,
198 base::Unretained(this),
199 "/test",
200 "<b>Worked!</b>",
201 "text/html",
202 HTTP_OK));
204 scoped_ptr<URLFetcher> fetcher =
205 URLFetcher::Create(server_->GetURL("/test?q=foo"), URLFetcher::GET, this);
206 fetcher->SetRequestContext(request_context_getter_.get());
207 fetcher->Start();
208 WaitForResponses(1);
210 EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
211 EXPECT_EQ(HTTP_OK, fetcher->GetResponseCode());
212 EXPECT_EQ("<b>Worked!</b>", GetContentFromFetcher(*fetcher));
213 EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher));
215 EXPECT_EQ("/test?q=foo", request_relative_url_);
218 TEST_F(EmbeddedTestServerTest, ServeFilesFromDirectory) {
219 base::FilePath src_dir;
220 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
221 server_->ServeFilesFromDirectory(
222 src_dir.AppendASCII("net").AppendASCII("data"));
224 scoped_ptr<URLFetcher> fetcher =
225 URLFetcher::Create(server_->GetURL("/test.html"), URLFetcher::GET, this);
226 fetcher->SetRequestContext(request_context_getter_.get());
227 fetcher->Start();
228 WaitForResponses(1);
230 EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
231 EXPECT_EQ(HTTP_OK, fetcher->GetResponseCode());
232 EXPECT_EQ("<p>Hello World!</p>", GetContentFromFetcher(*fetcher));
233 EXPECT_EQ("", GetContentTypeFromFetcher(*fetcher));
236 TEST_F(EmbeddedTestServerTest, DefaultNotFoundResponse) {
237 scoped_ptr<URLFetcher> fetcher = URLFetcher::Create(
238 server_->GetURL("/non-existent"), URLFetcher::GET, this);
239 fetcher->SetRequestContext(request_context_getter_.get());
241 fetcher->Start();
242 WaitForResponses(1);
243 EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher->GetStatus().status());
244 EXPECT_EQ(HTTP_NOT_FOUND, fetcher->GetResponseCode());
247 TEST_F(EmbeddedTestServerTest, ConnectionListenerAccept) {
248 TestNetLog net_log;
249 net::AddressList address_list;
250 EXPECT_TRUE(server_->GetAddressList(&address_list));
252 scoped_ptr<StreamSocket> socket =
253 ClientSocketFactory::GetDefaultFactory()->CreateTransportClientSocket(
254 address_list, &net_log, NetLog::Source());
255 TestCompletionCallback callback;
256 ASSERT_EQ(OK, callback.GetResult(socket->Connect(callback.callback())));
258 connection_listener_.WaitUntilFirstConnectionAccepted();
260 EXPECT_EQ(1u, connection_listener_.SocketAcceptedCount());
261 EXPECT_FALSE(connection_listener_.DidReadFromSocket());
264 TEST_F(EmbeddedTestServerTest, ConnectionListenerRead) {
265 scoped_ptr<URLFetcher> fetcher = URLFetcher::Create(
266 server_->GetURL("/non-existent"), URLFetcher::GET, this);
267 fetcher->SetRequestContext(request_context_getter_.get());
269 fetcher->Start();
270 WaitForResponses(1);
271 EXPECT_EQ(1u, connection_listener_.SocketAcceptedCount());
272 EXPECT_TRUE(connection_listener_.DidReadFromSocket());
275 TEST_F(EmbeddedTestServerTest, ConcurrentFetches) {
276 server_->RegisterRequestHandler(
277 base::Bind(&EmbeddedTestServerTest::HandleRequest,
278 base::Unretained(this),
279 "/test1",
280 "Raspberry chocolate",
281 "text/html",
282 HTTP_OK));
283 server_->RegisterRequestHandler(
284 base::Bind(&EmbeddedTestServerTest::HandleRequest,
285 base::Unretained(this),
286 "/test2",
287 "Vanilla chocolate",
288 "text/html",
289 HTTP_OK));
290 server_->RegisterRequestHandler(
291 base::Bind(&EmbeddedTestServerTest::HandleRequest,
292 base::Unretained(this),
293 "/test3",
294 "No chocolates",
295 "text/plain",
296 HTTP_NOT_FOUND));
298 scoped_ptr<URLFetcher> fetcher1 =
299 URLFetcher::Create(server_->GetURL("/test1"), URLFetcher::GET, this);
300 fetcher1->SetRequestContext(request_context_getter_.get());
301 scoped_ptr<URLFetcher> fetcher2 =
302 URLFetcher::Create(server_->GetURL("/test2"), URLFetcher::GET, this);
303 fetcher2->SetRequestContext(request_context_getter_.get());
304 scoped_ptr<URLFetcher> fetcher3 =
305 URLFetcher::Create(server_->GetURL("/test3"), URLFetcher::GET, this);
306 fetcher3->SetRequestContext(request_context_getter_.get());
308 // Fetch the three URLs concurrently.
309 fetcher1->Start();
310 fetcher2->Start();
311 fetcher3->Start();
312 WaitForResponses(3);
314 EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher1->GetStatus().status());
315 EXPECT_EQ(HTTP_OK, fetcher1->GetResponseCode());
316 EXPECT_EQ("Raspberry chocolate", GetContentFromFetcher(*fetcher1));
317 EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher1));
319 EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher2->GetStatus().status());
320 EXPECT_EQ(HTTP_OK, fetcher2->GetResponseCode());
321 EXPECT_EQ("Vanilla chocolate", GetContentFromFetcher(*fetcher2));
322 EXPECT_EQ("text/html", GetContentTypeFromFetcher(*fetcher2));
324 EXPECT_EQ(URLRequestStatus::SUCCESS, fetcher3->GetStatus().status());
325 EXPECT_EQ(HTTP_NOT_FOUND, fetcher3->GetResponseCode());
326 EXPECT_EQ("No chocolates", GetContentFromFetcher(*fetcher3));
327 EXPECT_EQ("text/plain", GetContentTypeFromFetcher(*fetcher3));
330 // Below test exercises EmbeddedTestServer's ability to cope with the situation
331 // where there is no MessageLoop available on the thread at EmbeddedTestServer
332 // initialization and/or destruction.
334 typedef std::tr1::tuple<bool, bool> ThreadingTestParams;
336 class EmbeddedTestServerThreadingTest
337 : public testing::TestWithParam<ThreadingTestParams> {};
339 class EmbeddedTestServerThreadingTestDelegate
340 : public base::PlatformThread::Delegate,
341 public URLFetcherDelegate {
342 public:
343 EmbeddedTestServerThreadingTestDelegate(
344 bool message_loop_present_on_initialize,
345 bool message_loop_present_on_shutdown)
346 : message_loop_present_on_initialize_(message_loop_present_on_initialize),
347 message_loop_present_on_shutdown_(message_loop_present_on_shutdown) {}
349 // base::PlatformThread::Delegate:
350 void ThreadMain() override {
351 scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner;
352 base::Thread io_thread("io_thread");
353 base::Thread::Options thread_options;
354 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
355 ASSERT_TRUE(io_thread.StartWithOptions(thread_options));
356 io_thread_runner = io_thread.task_runner();
358 scoped_ptr<base::MessageLoop> loop;
359 if (message_loop_present_on_initialize_)
360 loop.reset(new base::MessageLoopForIO);
362 // Create the test server instance.
363 EmbeddedTestServer server;
364 base::FilePath src_dir;
365 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
366 ASSERT_TRUE(server.InitializeAndWaitUntilReady());
368 // Make a request and wait for the reply.
369 if (!loop)
370 loop.reset(new base::MessageLoopForIO);
372 scoped_ptr<URLFetcher> fetcher =
373 URLFetcher::Create(server.GetURL("/test?q=foo"), URLFetcher::GET, this);
374 fetcher->SetRequestContext(
375 new TestURLRequestContextGetter(loop->task_runner()));
376 fetcher->Start();
377 loop->Run();
378 fetcher.reset();
380 // Shut down.
381 if (message_loop_present_on_shutdown_)
382 loop.reset();
384 ASSERT_TRUE(server.ShutdownAndWaitUntilComplete());
387 // URLFetcherDelegate override.
388 void OnURLFetchComplete(const URLFetcher* source) override {
389 base::MessageLoop::current()->Quit();
392 private:
393 bool message_loop_present_on_initialize_;
394 bool message_loop_present_on_shutdown_;
396 DISALLOW_COPY_AND_ASSIGN(EmbeddedTestServerThreadingTestDelegate);
399 TEST_P(EmbeddedTestServerThreadingTest, RunTest) {
400 // The actual test runs on a separate thread so it can screw with the presence
401 // of a MessageLoop - the test suite already sets up a MessageLoop for the
402 // main test thread.
403 base::PlatformThreadHandle thread_handle;
404 EmbeddedTestServerThreadingTestDelegate delegate(
405 std::tr1::get<0>(GetParam()),
406 std::tr1::get<1>(GetParam()));
407 ASSERT_TRUE(base::PlatformThread::Create(0, &delegate, &thread_handle));
408 base::PlatformThread::Join(thread_handle);
411 INSTANTIATE_TEST_CASE_P(EmbeddedTestServerThreadingTestInstantiation,
412 EmbeddedTestServerThreadingTest,
413 testing::Combine(testing::Bool(), testing::Bool()));
415 } // namespace test_server
416 } // namespace net