blob: dc71d2bb6883c6692b3ebf908ddb0649b64ad09e [file] [log] [blame]
//
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "update_engine/chrome_browser_proxy_resolver.h"
#include <deque>
#include <string>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <base/macros.h>
#include <brillo/errors/error.h>
#include "network_proxy/dbus-proxies.h"
#include "network_proxy/dbus-proxy-mocks.h"
#include "update_engine/dbus_test_utils.h"
using ::testing::DoAll;
using ::testing::SaveArg;
using ::testing::StrEq;
using ::testing::_;
using org::chromium::NetworkProxyServiceInterfaceProxyMock;
using std::deque;
using std::string;
using std::vector;
namespace chromeos_update_engine {
namespace {
// Callback for ProxyResolver::GetProxiesForUrl() that copies |src| to |dest|.
void CopyProxies(deque<string>* dest, const deque<string>& src) {
*dest = src;
}
} // namespace
class ChromeBrowserProxyResolverTest : public ::testing::Test {
public:
ChromeBrowserProxyResolverTest() = default;
~ChromeBrowserProxyResolverTest() override = default;
protected:
// Adds a GoogleMock expectation for a call to |dbus_proxy_|'s
// ResolveProxyAsync method to resolve |url|.
void AddResolveProxyExpectation(const std::string& url) {
EXPECT_CALL(dbus_proxy_, ResolveProxyAsync(StrEq(url), _, _, _))
.WillOnce(DoAll(SaveArg<1>(&success_callback_),
SaveArg<2>(&error_callback_)));
}
NetworkProxyServiceInterfaceProxyMock dbus_proxy_;
ChromeBrowserProxyResolver resolver_{&dbus_proxy_};
// Callbacks that were passed to |dbus_proxy_|'s ResolveProxyAsync method.
base::Callback<void(const std::string&, const std::string&)>
success_callback_;
base::Callback<void(brillo::Error*)> error_callback_;
private:
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserProxyResolverTest);
};
TEST_F(ChromeBrowserProxyResolverTest, Parse) {
// Test ideas from
// http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list_unittest.cc
vector<string> inputs = {
"PROXY foopy:10",
" DIRECT", // leading space.
"PROXY foopy1 ; proxy foopy2;\t DIRECT",
"proxy foopy1 ; SOCKS foopy2",
"DIRECT ; proxy foopy1 ; DIRECT ; SOCKS5 foopy2;DIRECT ",
"DIRECT ; proxy foopy1:80; DIRECT ; DIRECT",
"PROXY-foopy:10",
"PROXY",
"PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;",
"HTTP foopy1; SOCKS5 foopy2",
};
vector<deque<string>> outputs = {
{"http://foopy:10", kNoProxy},
{kNoProxy},
{"http://foopy1", "http://foopy2", kNoProxy},
{"http://foopy1", "socks4://foopy2", kNoProxy},
{kNoProxy, "http://foopy1", kNoProxy, "socks5://foopy2", kNoProxy},
{kNoProxy, "http://foopy1:80", kNoProxy, kNoProxy},
{kNoProxy},
{kNoProxy},
{"http://foopy1", "socks5://foopy2", kNoProxy},
{"socks5://foopy2", kNoProxy},
};
ASSERT_EQ(inputs.size(), outputs.size());
for (size_t i = 0; i < inputs.size(); i++) {
deque<string> results =
ChromeBrowserProxyResolver::ParseProxyString(inputs[i]);
deque<string>& expected = outputs[i];
EXPECT_EQ(results.size(), expected.size()) << "i = " << i;
if (expected.size() != results.size())
continue;
for (size_t j = 0; j < expected.size(); j++) {
EXPECT_EQ(expected[j], results[j]) << "i = " << i;
}
}
}
TEST_F(ChromeBrowserProxyResolverTest, Success) {
const char kUrl[] = "http://example.com/blah";
const char kProxyConfig[] = "SOCKS5 192.168.52.83:5555;DIRECT";
AddResolveProxyExpectation(kUrl);
deque<string> proxies;
resolver_.GetProxiesForUrl(kUrl, base::Bind(&CopyProxies, &proxies));
// Run the D-Bus success callback and verify that the proxies are passed to
// the supplied function.
ASSERT_FALSE(success_callback_.is_null());
success_callback_.Run(kProxyConfig, string());
ASSERT_EQ(2u, proxies.size());
EXPECT_EQ("socks5://192.168.52.83:5555", proxies[0]);
EXPECT_EQ(kNoProxy, proxies[1]);
}
TEST_F(ChromeBrowserProxyResolverTest, Failure) {
const char kUrl[] = "http://example.com/blah";
AddResolveProxyExpectation(kUrl);
deque<string> proxies;
resolver_.GetProxiesForUrl(kUrl, base::Bind(&CopyProxies, &proxies));
// Run the D-Bus error callback and verify that the supplied function is
// instructed to use a direct connection.
ASSERT_FALSE(error_callback_.is_null());
brillo::ErrorPtr error = brillo::Error::Create(FROM_HERE, "", "", "");
error_callback_.Run(error.get());
ASSERT_EQ(1u, proxies.size());
EXPECT_EQ(kNoProxy, proxies[0]);
}
TEST_F(ChromeBrowserProxyResolverTest, CancelCallback) {
const char kUrl[] = "http://example.com/blah";
AddResolveProxyExpectation(kUrl);
int called = 0;
auto callback = base::Bind(
[](int* called, const deque<string>& proxies) { (*called)++; }, &called);
ProxyRequestId request = resolver_.GetProxiesForUrl(kUrl, callback);
// Cancel the request and then run the D-Bus success callback. The original
// callback shouldn't be run.
EXPECT_TRUE(resolver_.CancelProxyRequest(request));
ASSERT_FALSE(success_callback_.is_null());
success_callback_.Run("DIRECT", string());
EXPECT_EQ(0, called);
}
TEST_F(ChromeBrowserProxyResolverTest, CancelCallbackTwice) {
const char kUrl[] = "http://example.com/blah";
AddResolveProxyExpectation(kUrl);
deque<string> proxies;
ProxyRequestId request =
resolver_.GetProxiesForUrl(kUrl, base::Bind(&CopyProxies, &proxies));
// Cancel the same request twice. The second call should fail.
EXPECT_TRUE(resolver_.CancelProxyRequest(request));
EXPECT_FALSE(resolver_.CancelProxyRequest(request));
}
} // namespace chromeos_update_engine