1// 2// Copyright (C) 2011 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "update_engine/chrome_browser_proxy_resolver.h" 18 19#include <deque> 20#include <string> 21#include <vector> 22 23#include <gtest/gtest.h> 24 25#include <base/bind.h> 26#include <brillo/make_unique_ptr.h> 27#include <brillo/message_loops/fake_message_loop.h> 28 29#include "libcros/dbus-proxies.h" 30#include "libcros/dbus-proxy-mocks.h" 31#include "update_engine/dbus_test_utils.h" 32 33using ::testing::Return; 34using ::testing::StrEq; 35using ::testing::_; 36using brillo::MessageLoop; 37using org::chromium::LibCrosServiceInterfaceProxyMock; 38using org::chromium::UpdateEngineLibcrosProxyResolvedInterfaceProxyMock; 39using std::deque; 40using std::string; 41using std::vector; 42 43namespace chromeos_update_engine { 44 45class ChromeBrowserProxyResolverTest : public ::testing::Test { 46 protected: 47 ChromeBrowserProxyResolverTest() 48 : service_interface_mock_(new LibCrosServiceInterfaceProxyMock()), 49 ue_proxy_resolved_interface_mock_( 50 new UpdateEngineLibcrosProxyResolvedInterfaceProxyMock()), 51 libcros_proxy_( 52 brillo::make_unique_ptr(service_interface_mock_), 53 brillo::make_unique_ptr(ue_proxy_resolved_interface_mock_)) {} 54 55 void SetUp() override { 56 loop_.SetAsCurrent(); 57 // The ProxyResolved signal should be subscribed to. 58 MOCK_SIGNAL_HANDLER_EXPECT_SIGNAL_HANDLER( 59 ue_proxy_resolved_signal_, 60 *ue_proxy_resolved_interface_mock_, 61 ProxyResolved); 62 63 EXPECT_TRUE(resolver_.Init()); 64 // Run the loop once to dispatch the successfully registered signal handler. 65 EXPECT_TRUE(loop_.RunOnce(false)); 66 } 67 68 void TearDown() override { 69 EXPECT_FALSE(loop_.PendingTasks()); 70 } 71 72 // Send the signal to the callback passed during registration of the 73 // ProxyResolved. 74 void SendReplySignal(const string& source_url, 75 const string& proxy_info, 76 const string& error_message); 77 78 void RunTest(bool chrome_replies, bool chrome_alive); 79 80 private: 81 brillo::FakeMessageLoop loop_{nullptr}; 82 83 // Local pointers to the mocks. The instances are owned by the 84 // |libcros_proxy_|. 85 LibCrosServiceInterfaceProxyMock* service_interface_mock_; 86 UpdateEngineLibcrosProxyResolvedInterfaceProxyMock* 87 ue_proxy_resolved_interface_mock_; 88 89 // The registered signal handler for the signal 90 // UpdateEngineLibcrosProxyResolvedInterface.ProxyResolved. 91 chromeos_update_engine::dbus_test_utils::MockSignalHandler< 92 void(const string&, const string&, const string&)> 93 ue_proxy_resolved_signal_; 94 95 LibCrosProxy libcros_proxy_; 96 ChromeBrowserProxyResolver resolver_{&libcros_proxy_}; 97}; 98 99 100void ChromeBrowserProxyResolverTest::SendReplySignal( 101 const string& source_url, 102 const string& proxy_info, 103 const string& error_message) { 104 ASSERT_TRUE(ue_proxy_resolved_signal_.IsHandlerRegistered()); 105 ue_proxy_resolved_signal_.signal_callback().Run( 106 source_url, proxy_info, error_message); 107} 108 109namespace { 110void CheckResponseResolved(const deque<string>& proxies, 111 void* /* pirv_data */) { 112 EXPECT_EQ(2U, proxies.size()); 113 EXPECT_EQ("socks5://192.168.52.83:5555", proxies[0]); 114 EXPECT_EQ(kNoProxy, proxies[1]); 115 MessageLoop::current()->BreakLoop(); 116} 117 118void CheckResponseNoReply(const deque<string>& proxies, void* /* pirv_data */) { 119 EXPECT_EQ(1U, proxies.size()); 120 EXPECT_EQ(kNoProxy, proxies[0]); 121 MessageLoop::current()->BreakLoop(); 122} 123} // namespace 124 125// chrome_replies should be set to whether or not we fake a reply from 126// chrome. If there's no reply, the resolver should time out. 127// If chrome_alive is false, assume that sending to chrome fails. 128void ChromeBrowserProxyResolverTest::RunTest(bool chrome_replies, 129 bool chrome_alive) { 130 char kUrl[] = "http://example.com/blah"; 131 char kProxyConfig[] = "SOCKS5 192.168.52.83:5555;DIRECT"; 132 133 EXPECT_CALL(*service_interface_mock_, 134 ResolveNetworkProxy(StrEq(kUrl), 135 StrEq(kLibCrosProxyResolveSignalInterface), 136 StrEq(kLibCrosProxyResolveName), 137 _, 138 _)) 139 .WillOnce(Return(chrome_alive)); 140 141 ProxiesResolvedFn get_proxies_response = &CheckResponseNoReply; 142 if (chrome_replies) { 143 get_proxies_response = &CheckResponseResolved; 144 MessageLoop::current()->PostDelayedTask( 145 FROM_HERE, 146 base::Bind(&ChromeBrowserProxyResolverTest::SendReplySignal, 147 base::Unretained(this), 148 kUrl, 149 kProxyConfig, 150 ""), 151 base::TimeDelta::FromSeconds(1)); 152 } 153 154 EXPECT_TRUE(resolver_.GetProxiesForUrl(kUrl, get_proxies_response, nullptr)); 155 MessageLoop::current()->Run(); 156} 157 158 159TEST_F(ChromeBrowserProxyResolverTest, ParseTest) { 160 // Test ideas from 161 // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list_unittest.cc 162 vector<string> inputs = { 163 "PROXY foopy:10", 164 " DIRECT", // leading space. 165 "PROXY foopy1 ; proxy foopy2;\t DIRECT", 166 "proxy foopy1 ; SOCKS foopy2", 167 "DIRECT ; proxy foopy1 ; DIRECT ; SOCKS5 foopy2;DIRECT ", 168 "DIRECT ; proxy foopy1:80; DIRECT ; DIRECT", 169 "PROXY-foopy:10", 170 "PROXY", 171 "PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;", 172 "HTTP foopy1; SOCKS5 foopy2"}; 173 vector<deque<string>> outputs = { 174 {"http://foopy:10", kNoProxy}, 175 {kNoProxy}, 176 {"http://foopy1", "http://foopy2", kNoProxy}, 177 {"http://foopy1", "socks4://foopy2", kNoProxy}, 178 {kNoProxy, "http://foopy1", kNoProxy, "socks5://foopy2", kNoProxy}, 179 {kNoProxy, "http://foopy1:80", kNoProxy, kNoProxy}, 180 {kNoProxy}, 181 {kNoProxy}, 182 {"http://foopy1", "socks5://foopy2", kNoProxy}, 183 {"socks5://foopy2", kNoProxy}}; 184 ASSERT_EQ(inputs.size(), outputs.size()); 185 186 for (size_t i = 0; i < inputs.size(); i++) { 187 deque<string> results = 188 ChromeBrowserProxyResolver::ParseProxyString(inputs[i]); 189 deque<string>& expected = outputs[i]; 190 EXPECT_EQ(results.size(), expected.size()) << "i = " << i; 191 if (expected.size() != results.size()) 192 continue; 193 for (size_t j = 0; j < expected.size(); j++) { 194 EXPECT_EQ(expected[j], results[j]) << "i = " << i; 195 } 196 } 197} 198 199TEST_F(ChromeBrowserProxyResolverTest, SuccessTest) { 200 RunTest(true, true); 201} 202 203TEST_F(ChromeBrowserProxyResolverTest, NoReplyTest) { 204 RunTest(false, true); 205} 206 207TEST_F(ChromeBrowserProxyResolverTest, NoChromeTest) { 208 RunTest(false, false); 209} 210 211} // namespace chromeos_update_engine 212