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 <string>
6
7#include "base/bind.h"
8#include "base/compiler_specific.h"
9#include "base/location.h"
10#include "base/memory/ref_counted.h"
11#include "base/message_loop/message_loop.h"
12#include "base/message_loop/message_loop_proxy.h"
13#include "base/single_thread_task_runner.h"
14#include "base/strings/stringprintf.h"
15#include "base/synchronization/waitable_event.h"
16#include "base/threading/thread.h"
17#include "chrome/test/chromedriver/net/net_util.h"
18#include "chrome/test/chromedriver/net/url_request_context_getter.h"
19#include "net/base/ip_endpoint.h"
20#include "net/base/net_errors.h"
21#include "net/server/http_server.h"
22#include "net/server/http_server_request_info.h"
23#include "net/socket/tcp_server_socket.h"
24#include "net/url_request/url_request_context_getter.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27namespace {
28
29class FetchUrlTest : public testing::Test,
30                     public net::HttpServer::Delegate {
31 public:
32  FetchUrlTest()
33      : io_thread_("io"),
34        response_(kSendHello) {
35    base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
36    CHECK(io_thread_.StartWithOptions(options));
37    context_getter_ = new URLRequestContextGetter(
38        io_thread_.message_loop_proxy());
39    base::WaitableEvent event(false, false);
40    io_thread_.message_loop_proxy()->PostTask(
41        FROM_HERE,
42        base::Bind(&FetchUrlTest::InitOnIO,
43                   base::Unretained(this), &event));
44    event.Wait();
45  }
46
47  virtual ~FetchUrlTest() {
48    base::WaitableEvent event(false, false);
49    io_thread_.message_loop_proxy()->PostTask(
50        FROM_HERE,
51        base::Bind(&FetchUrlTest::DestroyServerOnIO,
52                   base::Unretained(this), &event));
53    event.Wait();
54  }
55
56  void InitOnIO(base::WaitableEvent* event) {
57    scoped_ptr<net::ServerSocket> server_socket(
58        new net::TCPServerSocket(NULL, net::NetLog::Source()));
59    server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1);
60    server_.reset(new net::HttpServer(server_socket.Pass(), this));
61    net::IPEndPoint address;
62    CHECK_EQ(net::OK, server_->GetLocalAddress(&address));
63    server_url_ = base::StringPrintf("http://127.0.0.1:%d", address.port());
64    event->Signal();
65  }
66
67  void DestroyServerOnIO(base::WaitableEvent* event) {
68    server_.reset(NULL);
69    event->Signal();
70  }
71
72  // Overridden from net::HttpServer::Delegate:
73  virtual void OnConnect(int connection_id) OVERRIDE {}
74
75  virtual void OnHttpRequest(int connection_id,
76                             const net::HttpServerRequestInfo& info) OVERRIDE {
77    switch (response_) {
78      case kSendHello:
79        server_->Send200(connection_id, "hello", "text/plain");
80        break;
81      case kSend404:
82        server_->Send404(connection_id);
83        break;
84      case kClose:
85        server_->Close(connection_id);
86        break;
87      default:
88        break;
89    }
90  }
91
92  virtual void OnWebSocketRequest(
93      int connection_id,
94      const net::HttpServerRequestInfo& info) OVERRIDE {}
95  virtual void OnWebSocketMessage(int connection_id,
96                                  const std::string& data) OVERRIDE {}
97  virtual void OnClose(int connection_id) OVERRIDE {}
98
99 protected:
100  enum ServerResponse {
101    kSendHello = 0,
102    kSend404,
103    kClose,
104  };
105
106  base::Thread io_thread_;
107  ServerResponse response_;
108  scoped_ptr<net::HttpServer> server_;
109  scoped_refptr<URLRequestContextGetter> context_getter_;
110  std::string server_url_;
111};
112
113}  // namespace
114
115TEST_F(FetchUrlTest, Http200) {
116  std::string response("stuff");
117  ASSERT_TRUE(FetchUrl(server_url_, context_getter_.get(), &response));
118  ASSERT_STREQ("hello", response.c_str());
119}
120
121TEST_F(FetchUrlTest, HttpNon200) {
122  response_ = kSend404;
123  std::string response("stuff");
124  ASSERT_FALSE(FetchUrl(server_url_, context_getter_.get(), &response));
125  ASSERT_STREQ("stuff", response.c_str());
126}
127
128TEST_F(FetchUrlTest, ConnectionClose) {
129  response_ = kClose;
130  std::string response("stuff");
131  ASSERT_FALSE(FetchUrl(server_url_, context_getter_.get(), &response));
132  ASSERT_STREQ("stuff", response.c_str());
133}
134
135TEST_F(FetchUrlTest, NoServer) {
136  std::string response("stuff");
137  ASSERT_FALSE(
138      FetchUrl("http://localhost:33333", context_getter_.get(), &response));
139  ASSERT_STREQ("stuff", response.c_str());
140}
141