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