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_listen_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    net::TCPListenSocketFactory factory("127.0.0.1", 0);
58    server_ = new net::HttpServer(factory, this);
59    net::IPEndPoint address;
60    CHECK_EQ(net::OK, server_->GetLocalAddress(&address));
61    server_url_ = base::StringPrintf("http://127.0.0.1:%d", address.port());
62    event->Signal();
63  }
64
65  void DestroyServerOnIO(base::WaitableEvent* event) {
66    server_ = NULL;
67    event->Signal();
68  }
69
70  // Overridden from net::HttpServer::Delegate:
71  virtual void OnHttpRequest(int connection_id,
72                             const net::HttpServerRequestInfo& info) OVERRIDE {
73    switch (response_) {
74      case kSendHello:
75        server_->Send200(connection_id, "hello", "text/plain");
76        break;
77      case kSend404:
78        server_->Send404(connection_id);
79        break;
80      case kClose:
81        // net::HttpServer doesn't allow us to close connection during callback.
82        base::MessageLoop::current()->PostTask(
83            FROM_HERE,
84            base::Bind(&net::HttpServer::Close, server_, connection_id));
85        break;
86      default:
87        break;
88    }
89  }
90
91  virtual void OnWebSocketRequest(
92      int connection_id,
93      const net::HttpServerRequestInfo& info) OVERRIDE {}
94  virtual void OnWebSocketMessage(int connection_id,
95                                  const std::string& data) OVERRIDE {}
96  virtual void OnClose(int connection_id) OVERRIDE {}
97
98 protected:
99  enum ServerResponse {
100    kSendHello = 0,
101    kSend404,
102    kClose,
103  };
104
105  base::Thread io_thread_;
106  ServerResponse response_;
107  scoped_refptr<net::HttpServer> server_;
108  scoped_refptr<URLRequestContextGetter> context_getter_;
109  std::string server_url_;
110};
111
112}  // namespace
113
114TEST_F(FetchUrlTest, Http200) {
115  std::string response("stuff");
116  ASSERT_TRUE(FetchUrl(server_url_, context_getter_.get(), &response));
117  ASSERT_STREQ("hello", response.c_str());
118}
119
120TEST_F(FetchUrlTest, HttpNon200) {
121  response_ = kSend404;
122  std::string response("stuff");
123  ASSERT_FALSE(FetchUrl(server_url_, context_getter_.get(), &response));
124  ASSERT_STREQ("stuff", response.c_str());
125}
126
127TEST_F(FetchUrlTest, ConnectionClose) {
128  response_ = kClose;
129  std::string response("stuff");
130  ASSERT_FALSE(FetchUrl(server_url_, context_getter_.get(), &response));
131  ASSERT_STREQ("stuff", response.c_str());
132}
133
134TEST_F(FetchUrlTest, NoServer) {
135  std::string response("stuff");
136  ASSERT_FALSE(
137      FetchUrl("http://localhost:33333", context_getter_.get(), &response));
138  ASSERT_STREQ("stuff", response.c_str());
139}
140