1 // Copyright 2017 The Chromium OS 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 <brillo/http/http_proxy.h>
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include <base/bind.h>
13 #include <brillo/http/http_transport.h>
14 #include <chromeos/dbus/service_constants.h>
15 #include <dbus/mock_bus.h>
16 #include <dbus/mock_object_proxy.h>
17 #include <gtest/gtest.h>
18
19 using ::testing::_;
20 using ::testing::ElementsAre;
21 using ::testing::Invoke;
22 using ::testing::Return;
23
24 namespace {
25 constexpr char kTestUrl[] = "http://www.example.com/test";
26 } // namespace
27
28 namespace brillo {
29 namespace http {
30
31 class HttpProxyTest : public testing::Test {
32 public:
ResolveProxyHandlerAsync(dbus::MethodCall * method_call,int timeout_msec,dbus::ObjectProxy::ResponseCallback * callback)33 void ResolveProxyHandlerAsync(dbus::MethodCall* method_call,
34 int timeout_msec,
35 dbus::ObjectProxy::ResponseCallback* callback) {
36 if (null_dbus_response_) {
37 std::move(*callback).Run(nullptr);
38 return;
39 }
40 std::move(*callback).Run(CreateDBusResponse(method_call).get());
41 }
42
ResolveProxyHandler(dbus::MethodCall * method_call,int timeout_msec)43 std::unique_ptr<dbus::Response> ResolveProxyHandler(
44 dbus::MethodCall* method_call, int timeout_msec) {
45 if (null_dbus_response_) {
46 return std::unique_ptr<dbus::Response>();
47 }
48 return CreateDBusResponse(method_call);
49 }
50
51 MOCK_METHOD(void,
52 GetProxiesCallback,
53 (bool, const std::vector<std::string>&));
54
55 protected:
HttpProxyTest()56 HttpProxyTest() {
57 dbus::Bus::Options options;
58 options.bus_type = dbus::Bus::SYSTEM;
59 bus_ = new dbus::MockBus(options);
60 object_proxy_ = new dbus::MockObjectProxy(
61 bus_.get(), chromeos::kNetworkProxyServiceName,
62 dbus::ObjectPath(chromeos::kNetworkProxyServicePath));
63 EXPECT_CALL(*bus_, GetObjectProxy(chromeos::kNetworkProxyServiceName,
64 dbus::ObjectPath(
65 chromeos::kNetworkProxyServicePath)))
66 .WillOnce(Return(object_proxy_.get()));
67 }
68
CreateDBusResponse(dbus::MethodCall * method_call)69 std::unique_ptr<dbus::Response> CreateDBusResponse(
70 dbus::MethodCall* method_call) {
71 EXPECT_EQ(method_call->GetInterface(),
72 chromeos::kNetworkProxyServiceInterface);
73 EXPECT_EQ(method_call->GetMember(),
74 chromeos::kNetworkProxyServiceResolveProxyMethod);
75 method_call->SetSerial(1); // Needs to be non-zero or it fails.
76 std::unique_ptr<dbus::Response> response =
77 dbus::Response::FromMethodCall(method_call);
78 dbus::MessageWriter writer(response.get());
79 writer.AppendString(proxy_info_);
80 if (invalid_dbus_response_) {
81 return response;
82 }
83 writer.AppendString(proxy_err_);
84 return response;
85 }
86
87 scoped_refptr<dbus::MockBus> bus_;
88 scoped_refptr<dbus::MockObjectProxy> object_proxy_;
89
90 std::string proxy_info_;
91 std::string proxy_err_;
92 bool null_dbus_response_ = false;
93 bool invalid_dbus_response_ = false;
94
95 private:
96 DISALLOW_COPY_AND_ASSIGN(HttpProxyTest);
97 };
98
TEST_F(HttpProxyTest,DBusNullResponseFails)99 TEST_F(HttpProxyTest, DBusNullResponseFails) {
100 std::vector<std::string> proxies;
101 null_dbus_response_ = true;
102 EXPECT_CALL(*object_proxy_, CallMethodAndBlock(_, _))
103 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandler));
104 EXPECT_FALSE(GetChromeProxyServers(bus_, kTestUrl, &proxies));
105 }
106
TEST_F(HttpProxyTest,DBusInvalidResponseFails)107 TEST_F(HttpProxyTest, DBusInvalidResponseFails) {
108 std::vector<std::string> proxies;
109 invalid_dbus_response_ = true;
110 EXPECT_CALL(*object_proxy_, CallMethodAndBlock(_, _))
111 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandler));
112 EXPECT_FALSE(GetChromeProxyServers(bus_, kTestUrl, &proxies));
113 }
114
TEST_F(HttpProxyTest,NoProxies)115 TEST_F(HttpProxyTest, NoProxies) {
116 std::vector<std::string> proxies;
117 EXPECT_CALL(*object_proxy_, CallMethodAndBlock(_, _))
118 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandler));
119 EXPECT_TRUE(GetChromeProxyServers(bus_, kTestUrl, &proxies));
120 EXPECT_THAT(proxies, ElementsAre(kDirectProxy));
121 }
122
TEST_F(HttpProxyTest,MultipleProxiesWithoutDirect)123 TEST_F(HttpProxyTest, MultipleProxiesWithoutDirect) {
124 proxy_info_ = "proxy example.com; socks5 foo.com;";
125 std::vector<std::string> proxies;
126 EXPECT_CALL(*object_proxy_, CallMethodAndBlock(_, _))
127 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandler));
128 EXPECT_TRUE(GetChromeProxyServers(bus_, kTestUrl, &proxies));
129 EXPECT_THAT(proxies, ElementsAre("http://example.com", "socks5://foo.com",
130 kDirectProxy));
131 }
132
TEST_F(HttpProxyTest,MultipleProxiesWithDirect)133 TEST_F(HttpProxyTest, MultipleProxiesWithDirect) {
134 proxy_info_ = "socks foo.com; Https example.com ; badproxy example2.com ; "
135 "socks5 test.com ; proxy foobar.com; DIRECT ";
136 std::vector<std::string> proxies;
137 EXPECT_CALL(*object_proxy_, CallMethodAndBlock(_, _))
138 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandler));
139 EXPECT_TRUE(GetChromeProxyServers(bus_, kTestUrl, &proxies));
140 EXPECT_THAT(proxies, ElementsAre("socks4://foo.com", "https://example.com",
141 "socks5://test.com", "http://foobar.com",
142 kDirectProxy));
143 }
144
TEST_F(HttpProxyTest,DBusNullResponseFailsAsync)145 TEST_F(HttpProxyTest, DBusNullResponseFailsAsync) {
146 null_dbus_response_ = true;
147 EXPECT_CALL(*object_proxy_, DoCallMethod(_, _, _))
148 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandlerAsync));
149 EXPECT_CALL(*this, GetProxiesCallback(false, _));
150 GetChromeProxyServersAsync(
151 bus_, kTestUrl,
152 base::Bind(&HttpProxyTest::GetProxiesCallback, base::Unretained(this)));
153 }
154
TEST_F(HttpProxyTest,DBusInvalidResponseFailsAsync)155 TEST_F(HttpProxyTest, DBusInvalidResponseFailsAsync) {
156 invalid_dbus_response_ = true;
157 EXPECT_CALL(*object_proxy_, DoCallMethod(_, _, _))
158 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandlerAsync));
159 EXPECT_CALL(*this, GetProxiesCallback(false, _));
160 GetChromeProxyServersAsync(
161 bus_, kTestUrl,
162 base::Bind(&HttpProxyTest::GetProxiesCallback, base::Unretained(this)));
163 }
164
165 // We don't need to test all the proxy cases with async because that will be
166 // using the same internal parsing code.
TEST_F(HttpProxyTest,MultipleProxiesWithDirectAsync)167 TEST_F(HttpProxyTest, MultipleProxiesWithDirectAsync) {
168 proxy_info_ = "socks foo.com; Https example.com ; badproxy example2.com ; "
169 "socks5 test.com ; proxy foobar.com; DIRECT ";
170 std::vector<std::string> expected = {
171 "socks4://foo.com", "https://example.com", "socks5://test.com",
172 "http://foobar.com", kDirectProxy};
173 EXPECT_CALL(*object_proxy_, DoCallMethod(_, _, _))
174 .WillOnce(Invoke(this, &HttpProxyTest::ResolveProxyHandlerAsync));
175 EXPECT_CALL(*this, GetProxiesCallback(true, expected));
176 GetChromeProxyServersAsync(
177 bus_, kTestUrl,
178 base::Bind(&HttpProxyTest::GetProxiesCallback, base::Unretained(this)));
179 }
180
181 } // namespace http
182 } // namespace brillo
183