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