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 "chrome/test/chromedriver/net/net_util.h"
6 
7 #include <string>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/message_loop/message_pump_type.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/test/task_environment.h"
19 #include "base/threading/thread.h"
20 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
21 #include "mojo/core/embedder/embedder.h"
22 #include "net/base/ip_endpoint.h"
23 #include "net/base/net_errors.h"
24 #include "net/log/net_log_source.h"
25 #include "net/server/http_server.h"
26 #include "net/server/http_server_request_info.h"
27 #include "net/socket/tcp_server_socket.h"
28 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
29 #include "net/url_request/url_request_context_getter.h"
30 #include "services/network/public/cpp/shared_url_loader_factory.h"
31 #include "services/network/transitional_url_loader_factory_owner.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 
34 namespace {
35 
36 class FetchUrlTest : public testing::Test,
37                      public net::HttpServer::Delegate {
38  public:
FetchUrlTest()39   FetchUrlTest()
40       : io_thread_("io"),
41         response_(kSendHello),
42         task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {
43     base::Thread::Options options(base::MessagePumpType::IO, 0);
44     CHECK(io_thread_.StartWithOptions(options));
45 
46     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
47                               base::WaitableEvent::InitialState::NOT_SIGNALED);
48     io_thread_.task_runner()->PostTask(
49         FROM_HERE, base::BindOnce(&FetchUrlTest::InitOnIO,
50                                   base::Unretained(this), &event));
51 
52     event.Wait();
53   }
54 
~FetchUrlTest()55   ~FetchUrlTest() override {
56     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
57                               base::WaitableEvent::InitialState::NOT_SIGNALED);
58     io_thread_.task_runner()->PostTask(
59         FROM_HERE, base::BindOnce(&FetchUrlTest::DestroyServerOnIO,
60                                   base::Unretained(this), &event));
61     event.Wait();
62   }
63 
SetUpTestSuite()64   static void SetUpTestSuite() { mojo::core::Init(); }
65 
InitOnIO(base::WaitableEvent * event)66   void InitOnIO(base::WaitableEvent* event) {
67     scoped_refptr<URLRequestContextGetter> context_getter =
68         new URLRequestContextGetter(io_thread_.task_runner());
69     url_loader_factory_owner_ =
70         std::make_unique<network::TransitionalURLLoaderFactoryOwner>(
71             context_getter);
72     url_loader_factory_ =
73         url_loader_factory_owner_->GetURLLoaderFactory().get();
74 
75     std::unique_ptr<net::ServerSocket> server_socket(
76         new net::TCPServerSocket(NULL, net::NetLogSource()));
77     server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1);
78     server_.reset(new net::HttpServer(std::move(server_socket), this));
79     net::IPEndPoint address;
80     CHECK_EQ(net::OK, server_->GetLocalAddress(&address));
81     server_url_ = base::StringPrintf("http://127.0.0.1:%d", address.port());
82     event->Signal();
83   }
84 
DestroyServerOnIO(base::WaitableEvent * event)85   void DestroyServerOnIO(base::WaitableEvent* event) {
86     url_loader_factory_owner_.reset();
87     server_.reset(NULL);
88     event->Signal();
89   }
90 
91   // Overridden from net::HttpServer::Delegate:
OnConnect(int connection_id)92   void OnConnect(int connection_id) override {}
93 
OnHttpRequest(int connection_id,const net::HttpServerRequestInfo & info)94   void OnHttpRequest(int connection_id,
95                      const net::HttpServerRequestInfo& info) override {
96     switch (response_) {
97       case kSendHello:
98         server_->Send200(connection_id, "hello", "text/plain",
99                          TRAFFIC_ANNOTATION_FOR_TESTS);
100         break;
101       case kSend404:
102         server_->Send404(connection_id, TRAFFIC_ANNOTATION_FOR_TESTS);
103         break;
104       case kClose:
105         server_->Close(connection_id);
106         break;
107       default:
108         break;
109     }
110   }
111 
DoFetchURL(const std::string & server_url,std::string * response)112   bool DoFetchURL(const std::string& server_url, std::string* response) {
113     SetIOCapableTaskRunnerForTest(io_thread_.task_runner());
114     return FetchUrl(server_url, url_loader_factory_, response);
115   }
116 
OnWebSocketRequest(int connection_id,const net::HttpServerRequestInfo & info)117   void OnWebSocketRequest(int connection_id,
118                           const net::HttpServerRequestInfo& info) override {}
OnWebSocketMessage(int connection_id,std::string data)119   void OnWebSocketMessage(int connection_id, std::string data) override {}
OnClose(int connection_id)120   void OnClose(int connection_id) override {}
121 
122  protected:
123   enum ServerResponse {
124     kSendHello = 0,
125     kSend404,
126     kClose,
127   };
128 
129   base::Thread io_thread_;
130   ServerResponse response_;
131   std::unique_ptr<net::HttpServer> server_;
132   std::unique_ptr<network::TransitionalURLLoaderFactoryOwner>
133       url_loader_factory_owner_;
134   network::mojom::URLLoaderFactory* url_loader_factory_;
135   std::string server_url_;
136   base::test::TaskEnvironment task_environment_;
137 };
138 
139 }  // namespace
140 
141 #if !defined(THREAD_SANITIZER)
TEST_F(FetchUrlTest,Http200)142 TEST_F(FetchUrlTest, Http200) {
143   std::string response("stuff");
144   ASSERT_TRUE(DoFetchURL(server_url_, &response));
145   ASSERT_STREQ("hello", response.c_str());
146 }
147 #endif
148 
149 #if !defined(THREAD_SANITIZER)
TEST_F(FetchUrlTest,HttpNon200)150 TEST_F(FetchUrlTest, HttpNon200) {
151   response_ = kSend404;
152   std::string response("stuff");
153   ASSERT_FALSE(DoFetchURL(server_url_, &response));
154   ASSERT_STREQ("stuff", response.c_str());
155 }
156 #endif
157 
158 #if !defined(THREAD_SANITIZER)
TEST_F(FetchUrlTest,ConnectionClose)159 TEST_F(FetchUrlTest, ConnectionClose) {
160   response_ = kClose;
161   std::string response("stuff");
162   ASSERT_FALSE(DoFetchURL(server_url_, &response));
163   ASSERT_STREQ("stuff", response.c_str());
164 }
165 #endif
166 
167 #if !defined(THREAD_SANITIZER)
TEST_F(FetchUrlTest,NoServer)168 TEST_F(FetchUrlTest, NoServer) {
169   std::string response("stuff");
170   ASSERT_FALSE(DoFetchURL("http://localhost:33333", &response));
171   ASSERT_STREQ("stuff", response.c_str());
172 }
173 #endif
174