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