// // 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 #include #include #include #include #include #include #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* dest, const deque& 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 success_callback_; base::Callback 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 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> 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 results = ChromeBrowserProxyResolver::ParseProxyString(inputs[i]); deque& 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 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 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& 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 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