OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium 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 "base/timer.h" |
| 6 #include "base/perftimer.h" |
| 7 #include "net/base/net_errors.h" |
| 8 #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h" |
| 9 #include "net/proxy/mock_proxy_script_fetcher.h" |
| 10 #include "net/test/test_server.h" |
| 11 #include "net/url_request/url_request_test_util.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 |
| 14 namespace net { |
| 15 |
| 16 const char* const kPacUrl = "http://pacserver/script.pac"; |
| 17 |
| 18 namespace { |
| 19 |
| 20 // In net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc there are a few |
| 21 // tests that exercise DhcpProxyScriptAdapterFetcher end-to-end along with |
| 22 // WindowsDhcpProxyScriptFetcher, i.e. it tests the end-to-end usage of Win32 |
| 23 // APIs and the network. In this file we test only by stubbing out |
| 24 // functionality. |
| 25 |
| 26 // Version of DhcpProxyScriptAdapterFetcher that mocks out dependencies |
| 27 // to allow unit testing. |
| 28 class MockDhcpProxyScriptAdapterFetcher : public DhcpProxyScriptAdapterFetcher { |
| 29 public: |
| 30 explicit MockDhcpProxyScriptAdapterFetcher() |
| 31 : DhcpProxyScriptAdapterFetcher(new TestURLRequestContext()), |
| 32 dhcp_delay_ms_(1), |
| 33 timeout_ms_(100), |
| 34 configured_url_(kPacUrl), |
| 35 fetcher_delay_ms_(1), |
| 36 fetcher_result_(OK), |
| 37 pac_script_("bingo") { |
| 38 } |
| 39 |
| 40 void Cancel() { |
| 41 DhcpProxyScriptAdapterFetcher::Cancel(); |
| 42 fetcher_ = NULL; |
| 43 } |
| 44 |
| 45 std::string ImplGetPacURLFromDhcp(const std::string& adapter_name) OVERRIDE { |
| 46 base::PlatformThread::Sleep(dhcp_delay_ms_); |
| 47 return configured_url_; |
| 48 } |
| 49 |
| 50 virtual ProxyScriptFetcher* ImplCreateScriptFetcher( |
| 51 const GURL& url) OVERRIDE { |
| 52 // We don't maintain ownership of the fetcher, it is transferred to |
| 53 // the caller. |
| 54 fetcher_ = new MockProxyScriptFetcher(); |
| 55 fetcher_->SetURL(url); |
| 56 if (fetcher_delay_ms_ != -1) { |
| 57 fetcher_timer_.Start( |
| 58 base::TimeDelta::FromMilliseconds(fetcher_delay_ms_), |
| 59 this, &MockDhcpProxyScriptAdapterFetcher::OnFetcherTimer); |
| 60 } |
| 61 return fetcher_; |
| 62 } |
| 63 |
| 64 // Use a shorter timeout so tests can finish more quickly. |
| 65 virtual int ImplGetTimeoutMs() const OVERRIDE { |
| 66 return timeout_ms_; |
| 67 } |
| 68 |
| 69 void OnFetcherTimer() { |
| 70 DCHECK(fetcher_); |
| 71 fetcher_->NotifyFetchCompletion(fetcher_result_, pac_script_); |
| 72 fetcher_ = NULL; |
| 73 } |
| 74 |
| 75 bool IsWaitingForFetcher() const { |
| 76 return state_ == STATE_WAIT_URL; |
| 77 } |
| 78 |
| 79 bool WasCancelled() const { |
| 80 return state_ == STATE_CANCEL; |
| 81 } |
| 82 |
| 83 int dhcp_delay_ms_; |
| 84 int timeout_ms_; |
| 85 std::string configured_url_; |
| 86 int fetcher_delay_ms_; |
| 87 int fetcher_result_; |
| 88 std::string pac_script_; |
| 89 MockProxyScriptFetcher* fetcher_; |
| 90 base::OneShotTimer<MockDhcpProxyScriptAdapterFetcher> fetcher_timer_; |
| 91 }; |
| 92 |
| 93 class FetcherClient { |
| 94 public: |
| 95 FetcherClient() |
| 96 : finished_(false), |
| 97 fetcher_(new MockDhcpProxyScriptAdapterFetcher()), |
| 98 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 99 completion_callback_(this, &FetcherClient::OnCompletion)) { |
| 100 } |
| 101 |
| 102 void RunTest() { |
| 103 fetcher_->Fetch("adapter name", &completion_callback_); |
| 104 } |
| 105 |
| 106 void RunMessageLoopUntilComplete() { |
| 107 while (!finished_) { |
| 108 MessageLoop::current()->RunAllPending(); |
| 109 } |
| 110 MessageLoop::current()->RunAllPending(); |
| 111 } |
| 112 |
| 113 void OnCompletion(int result) { |
| 114 finished_ = true; |
| 115 } |
| 116 |
| 117 bool finished_; |
| 118 scoped_refptr<MockDhcpProxyScriptAdapterFetcher> fetcher_; |
| 119 string16 pac_text_; |
| 120 CompletionCallbackImpl<FetcherClient> completion_callback_; |
| 121 }; |
| 122 |
| 123 TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLNotInDhcp) { |
| 124 FetcherClient client; |
| 125 client.fetcher_->configured_url_ = ""; |
| 126 client.RunTest(); |
| 127 client.RunMessageLoopUntilComplete(); |
| 128 ASSERT_TRUE(client.fetcher_->DidFinish()); |
| 129 EXPECT_EQ(ERR_PAC_NOT_IN_DHCP, client.fetcher_->result()); |
| 130 EXPECT_EQ(string16(L""), client.fetcher_->pac_script()); |
| 131 } |
| 132 |
| 133 TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLInDhcp) { |
| 134 FetcherClient client; |
| 135 client.RunTest(); |
| 136 client.RunMessageLoopUntilComplete(); |
| 137 ASSERT_TRUE(client.fetcher_->DidFinish()); |
| 138 EXPECT_EQ(OK, client.fetcher_->result()); |
| 139 EXPECT_EQ(string16(L"bingo"), client.fetcher_->pac_script()); |
| 140 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->pac_url()); |
| 141 } |
| 142 |
| 143 TEST(DhcpProxyScriptAdapterFetcher, TimeoutDuringDhcp) { |
| 144 // Does a Fetch() with a long enough delay on accessing DHCP that the |
| 145 // fetcher should time out. This is to test a case manual testing found, |
| 146 // where under certain circumstances (e.g. adapter enabled for DHCP and |
| 147 // needs to retrieve its configuration from DHCP, but no DHCP server |
| 148 // present on the network) accessing DHCP can take on the order of tens |
| 149 // of seconds. |
| 150 FetcherClient client; |
| 151 client.fetcher_->dhcp_delay_ms_ = 20 * 1000; |
| 152 client.fetcher_->timeout_ms_ = 25; |
| 153 |
| 154 PerfTimer timer; |
| 155 client.RunTest(); |
| 156 client.RunMessageLoopUntilComplete(); |
| 157 |
| 158 // The timeout should occur within about 25 ms, way before the 20s set as |
| 159 // the API delay above. |
| 160 ASSERT_GT(base::TimeDelta::FromMilliseconds(35), timer.Elapsed()); |
| 161 ASSERT_TRUE(client.fetcher_->DidFinish()); |
| 162 EXPECT_EQ(ERR_TIMED_OUT, client.fetcher_->result()); |
| 163 EXPECT_EQ(string16(L""), client.fetcher_->pac_script()); |
| 164 EXPECT_EQ(GURL(), client.fetcher_->pac_url()); |
| 165 } |
| 166 |
| 167 TEST(DhcpProxyScriptAdapterFetcher, CancelWhileDhcp) { |
| 168 FetcherClient client; |
| 169 client.fetcher_->dhcp_delay_ms_ = 10; |
| 170 client.RunTest(); |
| 171 client.fetcher_->Cancel(); |
| 172 MessageLoop::current()->RunAllPending(); |
| 173 ASSERT_FALSE(client.fetcher_->DidFinish()); |
| 174 ASSERT_TRUE(client.fetcher_->WasCancelled()); |
| 175 EXPECT_EQ(ERR_ABORTED, client.fetcher_->result()); |
| 176 EXPECT_EQ(string16(L""), client.fetcher_->pac_script()); |
| 177 EXPECT_EQ(GURL(), client.fetcher_->pac_url()); |
| 178 } |
| 179 |
| 180 TEST(DhcpProxyScriptAdapterFetcher, CancelWhileFetcher) { |
| 181 FetcherClient client; |
| 182 // This causes the mock fetcher not to pretend the |
| 183 // fetcher finishes after a timeout. |
| 184 client.fetcher_->fetcher_delay_ms_ = -1; |
| 185 client.RunTest(); |
| 186 int max_loops = 4; |
| 187 while (!client.fetcher_->IsWaitingForFetcher() && max_loops--) { |
| 188 base::PlatformThread::Sleep(10); |
| 189 MessageLoop::current()->RunAllPending(); |
| 190 } |
| 191 client.fetcher_->Cancel(); |
| 192 MessageLoop::current()->RunAllPending(); |
| 193 ASSERT_FALSE(client.fetcher_->DidFinish()); |
| 194 ASSERT_TRUE(client.fetcher_->WasCancelled()); |
| 195 EXPECT_EQ(ERR_ABORTED, client.fetcher_->result()); |
| 196 EXPECT_EQ(string16(L""), client.fetcher_->pac_script()); |
| 197 // GetPacURL() still returns the URL fetched in this case. |
| 198 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->pac_url()); |
| 199 } |
| 200 |
| 201 TEST(DhcpProxyScriptAdapterFetcher, CancelAtCompletion) { |
| 202 FetcherClient client; |
| 203 client.RunTest(); |
| 204 client.RunMessageLoopUntilComplete(); |
| 205 client.fetcher_->Cancel(); |
| 206 // Canceling after you're done should have no effect, so these |
| 207 // are identical expectations to the NormalCaseURLInDhcp test. |
| 208 ASSERT_TRUE(client.fetcher_->DidFinish()); |
| 209 EXPECT_EQ(OK, client.fetcher_->result()); |
| 210 EXPECT_EQ(string16(L"bingo"), client.fetcher_->pac_script()); |
| 211 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->pac_url()); |
| 212 } |
| 213 |
| 214 // Does a real fetch on a mock DHCP configuration. |
| 215 class MockDhcpRealFetchProxyScriptAdapterFetcher |
| 216 : public MockDhcpProxyScriptAdapterFetcher { |
| 217 public: |
| 218 MockDhcpRealFetchProxyScriptAdapterFetcher() |
| 219 : MockDhcpProxyScriptAdapterFetcher(), |
| 220 url_request_context_(new TestURLRequestContext()) { |
| 221 } |
| 222 |
| 223 // Returns a real proxy script fetcher. |
| 224 ProxyScriptFetcher* ImplCreateScriptFetcher(const GURL& url) OVERRIDE { |
| 225 URLProxyScriptFetcher* fetcher = |
| 226 new ProxyScriptFetcherImpl(url_request_context_.get()); |
| 227 fetcher->SetURL(url); |
| 228 return fetcher; |
| 229 } |
| 230 |
| 231 scoped_refptr<URLRequestContext> url_request_context_; |
| 232 }; |
| 233 |
| 234 TEST(DhcpProxyScriptAdapterFetcher, MockDhcpRealFetch) { |
| 235 TestServer test_server( |
| 236 TestServer::TYPE_HTTP, |
| 237 FilePath(FILE_PATH_LITERAL("net/data/proxy_script_fetcher_unittest"))); |
| 238 ASSERT_TRUE(test_server.Start()); |
| 239 |
| 240 GURL configured_url = test_server.GetURL("files/downloadable.pac"); |
| 241 |
| 242 FetcherClient client; |
| 243 client.fetcher_ = new MockDhcpRealFetchProxyScriptAdapterFetcher(); |
| 244 client.fetcher_->configured_url_ = configured_url.spec(); |
| 245 client.RunTest(); |
| 246 client.RunMessageLoopUntilComplete(); |
| 247 ASSERT_TRUE(client.fetcher_->DidFinish()); |
| 248 EXPECT_EQ(OK, client.fetcher_->result()); |
| 249 EXPECT_EQ(string16(L"-downloadable.pac-\n"), client.fetcher_->pac_script()); |
| 250 EXPECT_EQ(configured_url, |
| 251 client.fetcher_->pac_url()); |
| 252 } |
| 253 |
| 254 } // namespace |
| 255 } // namespace net |
OLD | NEW |