12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/single_thread_task_runner.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/net_util.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/url_request_context_getter.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/ip_endpoint.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/server/http_server.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/server/http_server_request_info.h"
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/socket/tcp_server_socket.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FetchUrlTest : public testing::Test,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     public net::HttpServer::Delegate {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FetchUrlTest()
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : io_thread_("io"),
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        response_(kSendHello) {
35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(io_thread_.StartWithOptions(options));
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_getter_ = new URLRequestContextGetter(
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        io_thread_.message_loop_proxy());
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WaitableEvent event(false, false);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    io_thread_.message_loop_proxy()->PostTask(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&FetchUrlTest::InitOnIO,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this), &event));
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event.Wait();
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~FetchUrlTest() {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WaitableEvent event(false, false);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    io_thread_.message_loop_proxy()->PostTask(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&FetchUrlTest::DestroyServerOnIO,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this), &event));
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event.Wait();
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitOnIO(base::WaitableEvent* event) {
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<net::ServerSocket> server_socket(
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new net::TCPServerSocket(NULL, net::NetLog::Source()));
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1);
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    server_.reset(new net::HttpServer(server_socket.Pass(), this));
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::IPEndPoint address;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_EQ(net::OK, server_->GetLocalAddress(&address));
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    server_url_ = base::StringPrintf("http://127.0.0.1:%d", address.port());
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->Signal();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DestroyServerOnIO(base::WaitableEvent* event) {
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    server_.reset(NULL);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->Signal();
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from net::HttpServer::Delegate:
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnConnect(int connection_id) OVERRIDE {}
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnHttpRequest(int connection_id,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const net::HttpServerRequestInfo& info) OVERRIDE {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (response_) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case kSendHello:
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        server_->Send200(connection_id, "hello", "text/plain");
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case kSend404:
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        server_->Send404(connection_id);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case kClose:
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        server_->Close(connection_id);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWebSocketRequest(
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int connection_id,
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const net::HttpServerRequestInfo& info) OVERRIDE {}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWebSocketMessage(int connection_id,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& data) OVERRIDE {}
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnClose(int connection_id) OVERRIDE {}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum ServerResponse {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    kSendHello = 0,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    kSend404,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    kClose,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Thread io_thread_;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ServerResponse response_;
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<net::HttpServer> server_;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLRequestContextGetter> context_getter_;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string server_url_;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FetchUrlTest, Http200) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string response("stuff");
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(FetchUrl(server_url_, context_getter_.get(), &response));
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("hello", response.c_str());
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FetchUrlTest, HttpNon200) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  response_ = kSend404;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string response("stuff");
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_FALSE(FetchUrl(server_url_, context_getter_.get(), &response));
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("stuff", response.c_str());
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FetchUrlTest, ConnectionClose) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  response_ = kClose;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string response("stuff");
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_FALSE(FetchUrl(server_url_, context_getter_.get(), &response));
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("stuff", response.c_str());
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FetchUrlTest, NoServer) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string response("stuff");
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_FALSE(
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      FetchUrl("http://localhost:33333", context_getter_.get(), &response));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("stuff", response.c_str());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
141