Probably broke Win7 Tests (dbg)(6). http://build.chromium.org/p/chromium.win/builders...
[chromium-blink-merge.git] / net / proxy / dhcp_proxy_script_adapter_fetcher_win_unittest.cc
blob821e4ebd62a72dd61113c50d03664e752c09ec62
1 // Copyright (c) 2012 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.
5 #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/test/test_timeouts.h"
9 #include "base/threading/sequenced_worker_pool.h"
10 #include "base/timer/elapsed_timer.h"
11 #include "base/timer/timer.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/proxy/mock_proxy_script_fetcher.h"
15 #include "net/proxy/proxy_script_fetcher_impl.h"
16 #include "net/test/spawned_test_server/spawned_test_server.h"
17 #include "net/url_request/url_request_test_util.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace net {
22 namespace {
24 const char* const kPacUrl = "http://pacserver/script.pac";
26 // In net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc there are a few
27 // tests that exercise DhcpProxyScriptAdapterFetcher end-to-end along with
28 // DhcpProxyScriptFetcherWin, i.e. it tests the end-to-end usage of Win32
29 // APIs and the network. In this file we test only by stubbing out
30 // functionality.
32 // Version of DhcpProxyScriptAdapterFetcher that mocks out dependencies
33 // to allow unit testing.
34 class MockDhcpProxyScriptAdapterFetcher
35 : public DhcpProxyScriptAdapterFetcher {
36 public:
37 explicit MockDhcpProxyScriptAdapterFetcher(
38 URLRequestContext* context,
39 scoped_refptr<base::TaskRunner> task_runner)
40 : DhcpProxyScriptAdapterFetcher(context, task_runner),
41 dhcp_delay_(base::TimeDelta::FromMilliseconds(1)),
42 timeout_(TestTimeouts::action_timeout()),
43 configured_url_(kPacUrl),
44 fetcher_delay_ms_(1),
45 fetcher_result_(OK),
46 pac_script_("bingo") {
49 void Cancel() {
50 DhcpProxyScriptAdapterFetcher::Cancel();
51 fetcher_ = NULL;
54 virtual ProxyScriptFetcher* ImplCreateScriptFetcher() OVERRIDE {
55 // We don't maintain ownership of the fetcher, it is transferred to
56 // the caller.
57 fetcher_ = new MockProxyScriptFetcher();
58 if (fetcher_delay_ms_ != -1) {
59 fetcher_timer_.Start(FROM_HERE,
60 base::TimeDelta::FromMilliseconds(fetcher_delay_ms_),
61 this, &MockDhcpProxyScriptAdapterFetcher::OnFetcherTimer);
63 return fetcher_;
66 class DelayingDhcpQuery : public DhcpQuery {
67 public:
68 explicit DelayingDhcpQuery()
69 : DhcpQuery(),
70 test_finished_event_(true, false) {
73 std::string ImplGetPacURLFromDhcp(
74 const std::string& adapter_name) OVERRIDE {
75 base::ElapsedTimer timer;
76 test_finished_event_.TimedWait(dhcp_delay_);
77 return configured_url_;
80 base::WaitableEvent test_finished_event_;
81 base::TimeDelta dhcp_delay_;
82 std::string configured_url_;
85 virtual DhcpQuery* ImplCreateDhcpQuery() OVERRIDE {
86 dhcp_query_ = new DelayingDhcpQuery();
87 dhcp_query_->dhcp_delay_ = dhcp_delay_;
88 dhcp_query_->configured_url_ = configured_url_;
89 return dhcp_query_;
92 // Use a shorter timeout so tests can finish more quickly.
93 virtual base::TimeDelta ImplGetTimeout() const OVERRIDE {
94 return timeout_;
97 void OnFetcherTimer() {
98 // Note that there is an assumption by this mock implementation that
99 // DhcpProxyScriptAdapterFetcher::Fetch will call ImplCreateScriptFetcher
100 // and call Fetch on the fetcher before the message loop is re-entered.
101 // This holds true today, but if you hit this DCHECK the problem can
102 // possibly be resolved by having a separate subclass of
103 // MockProxyScriptFetcher that adds the delay internally (instead of
104 // the simple approach currently used in ImplCreateScriptFetcher above).
105 DCHECK(fetcher_ && fetcher_->has_pending_request());
106 fetcher_->NotifyFetchCompletion(fetcher_result_, pac_script_);
107 fetcher_ = NULL;
110 bool IsWaitingForFetcher() const {
111 return state() == STATE_WAIT_URL;
114 bool WasCancelled() const {
115 return state() == STATE_CANCEL;
118 void FinishTest() {
119 DCHECK(dhcp_query_);
120 dhcp_query_->test_finished_event_.Signal();
123 base::TimeDelta dhcp_delay_;
124 base::TimeDelta timeout_;
125 std::string configured_url_;
126 int fetcher_delay_ms_;
127 int fetcher_result_;
128 std::string pac_script_;
129 MockProxyScriptFetcher* fetcher_;
130 base::OneShotTimer<MockDhcpProxyScriptAdapterFetcher> fetcher_timer_;
131 scoped_refptr<DelayingDhcpQuery> dhcp_query_;
134 class FetcherClient {
135 public:
136 FetcherClient()
137 : url_request_context_(new TestURLRequestContext()),
138 worker_pool_(
139 new base::SequencedWorkerPool(4, "DhcpAdapterFetcherTest")),
140 fetcher_(new MockDhcpProxyScriptAdapterFetcher(
141 url_request_context_.get(),
142 worker_pool_->GetTaskRunnerWithShutdownBehavior(
143 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN))) {
146 ~FetcherClient() {
147 worker_pool_->Shutdown();
150 void WaitForResult(int expected_error) {
151 EXPECT_EQ(expected_error, callback_.WaitForResult());
154 void RunTest() {
155 fetcher_->Fetch("adapter name", callback_.callback());
158 void FinishTestAllowCleanup() {
159 fetcher_->FinishTest();
160 base::MessageLoop::current()->RunUntilIdle();
163 TestCompletionCallback callback_;
164 scoped_ptr<URLRequestContext> url_request_context_;
165 scoped_refptr<base::SequencedWorkerPool> worker_pool_;
166 scoped_ptr<MockDhcpProxyScriptAdapterFetcher> fetcher_;
167 base::string16 pac_text_;
170 TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLNotInDhcp) {
171 FetcherClient client;
172 client.fetcher_->configured_url_ = "";
173 client.RunTest();
174 client.WaitForResult(ERR_PAC_NOT_IN_DHCP);
175 ASSERT_TRUE(client.fetcher_->DidFinish());
176 EXPECT_EQ(ERR_PAC_NOT_IN_DHCP, client.fetcher_->GetResult());
177 EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
180 TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLInDhcp) {
181 FetcherClient client;
182 client.RunTest();
183 client.WaitForResult(OK);
184 ASSERT_TRUE(client.fetcher_->DidFinish());
185 EXPECT_EQ(OK, client.fetcher_->GetResult());
186 EXPECT_EQ(base::string16(L"bingo"), client.fetcher_->GetPacScript());
187 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
190 TEST(DhcpProxyScriptAdapterFetcher, TimeoutDuringDhcp) {
191 // Does a Fetch() with a long enough delay on accessing DHCP that the
192 // fetcher should time out. This is to test a case manual testing found,
193 // where under certain circumstances (e.g. adapter enabled for DHCP and
194 // needs to retrieve its configuration from DHCP, but no DHCP server
195 // present on the network) accessing DHCP can take on the order of tens
196 // of seconds.
197 FetcherClient client;
198 client.fetcher_->dhcp_delay_ = TestTimeouts::action_max_timeout();
199 client.fetcher_->timeout_ = base::TimeDelta::FromMilliseconds(25);
201 base::ElapsedTimer timer;
202 client.RunTest();
203 // An error different from this would be received if the timeout didn't
204 // kick in.
205 client.WaitForResult(ERR_TIMED_OUT);
207 ASSERT_TRUE(client.fetcher_->DidFinish());
208 EXPECT_EQ(ERR_TIMED_OUT, client.fetcher_->GetResult());
209 EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
210 EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
211 client.FinishTestAllowCleanup();
214 TEST(DhcpProxyScriptAdapterFetcher, CancelWhileDhcp) {
215 FetcherClient client;
216 client.RunTest();
217 client.fetcher_->Cancel();
218 base::MessageLoop::current()->RunUntilIdle();
219 ASSERT_FALSE(client.fetcher_->DidFinish());
220 ASSERT_TRUE(client.fetcher_->WasCancelled());
221 EXPECT_EQ(ERR_ABORTED, client.fetcher_->GetResult());
222 EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
223 EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
224 client.FinishTestAllowCleanup();
227 TEST(DhcpProxyScriptAdapterFetcher, CancelWhileFetcher) {
228 FetcherClient client;
229 // This causes the mock fetcher not to pretend the
230 // fetcher finishes after a timeout.
231 client.fetcher_->fetcher_delay_ms_ = -1;
232 client.RunTest();
233 int max_loops = 4;
234 while (!client.fetcher_->IsWaitingForFetcher() && max_loops--) {
235 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
236 base::MessageLoop::current()->RunUntilIdle();
238 client.fetcher_->Cancel();
239 base::MessageLoop::current()->RunUntilIdle();
240 ASSERT_FALSE(client.fetcher_->DidFinish());
241 ASSERT_TRUE(client.fetcher_->WasCancelled());
242 EXPECT_EQ(ERR_ABORTED, client.fetcher_->GetResult());
243 EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
244 // GetPacURL() still returns the URL fetched in this case.
245 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
246 client.FinishTestAllowCleanup();
249 TEST(DhcpProxyScriptAdapterFetcher, CancelAtCompletion) {
250 FetcherClient client;
251 client.RunTest();
252 client.WaitForResult(OK);
253 client.fetcher_->Cancel();
254 // Canceling after you're done should have no effect, so these
255 // are identical expectations to the NormalCaseURLInDhcp test.
256 ASSERT_TRUE(client.fetcher_->DidFinish());
257 EXPECT_EQ(OK, client.fetcher_->GetResult());
258 EXPECT_EQ(base::string16(L"bingo"), client.fetcher_->GetPacScript());
259 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
260 client.FinishTestAllowCleanup();
263 // Does a real fetch on a mock DHCP configuration.
264 class MockDhcpRealFetchProxyScriptAdapterFetcher
265 : public MockDhcpProxyScriptAdapterFetcher {
266 public:
267 explicit MockDhcpRealFetchProxyScriptAdapterFetcher(
268 URLRequestContext* context,
269 scoped_refptr<base::TaskRunner> task_runner)
270 : MockDhcpProxyScriptAdapterFetcher(context, task_runner),
271 url_request_context_(context) {
274 // Returns a real proxy script fetcher.
275 ProxyScriptFetcher* ImplCreateScriptFetcher() OVERRIDE {
276 ProxyScriptFetcher* fetcher =
277 new ProxyScriptFetcherImpl(url_request_context_);
278 return fetcher;
281 URLRequestContext* url_request_context_;
284 TEST(DhcpProxyScriptAdapterFetcher, MockDhcpRealFetch) {
285 SpawnedTestServer test_server(
286 SpawnedTestServer::TYPE_HTTP,
287 SpawnedTestServer::kLocalhost,
288 base::FilePath(
289 FILE_PATH_LITERAL("net/data/proxy_script_fetcher_unittest")));
290 ASSERT_TRUE(test_server.Start());
292 GURL configured_url = test_server.GetURL("files/downloadable.pac");
294 FetcherClient client;
295 TestURLRequestContext url_request_context;
296 scoped_refptr<base::TaskRunner> runner =
297 client.worker_pool_->GetTaskRunnerWithShutdownBehavior(
298 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
299 client.fetcher_.reset(
300 new MockDhcpRealFetchProxyScriptAdapterFetcher(
301 &url_request_context, runner));
302 client.fetcher_->configured_url_ = configured_url.spec();
303 client.RunTest();
304 client.WaitForResult(OK);
305 ASSERT_TRUE(client.fetcher_->DidFinish());
306 EXPECT_EQ(OK, client.fetcher_->GetResult());
307 EXPECT_EQ(base::string16(L"-downloadable.pac-\n"),
308 client.fetcher_->GetPacScript());
309 EXPECT_EQ(configured_url,
310 client.fetcher_->GetPacURL());
313 #define BASE_URL "http://corpserver/proxy.pac"
315 TEST(DhcpProxyScriptAdapterFetcher, SanitizeDhcpApiString) {
316 const size_t kBaseUrlLen = strlen(BASE_URL);
318 // Default case.
319 EXPECT_EQ(BASE_URL,
320 DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
321 BASE_URL, kBaseUrlLen));
323 // Trailing \n and no null-termination.
324 EXPECT_EQ(BASE_URL,
325 DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
326 BASE_URL "\nblablabla", kBaseUrlLen + 1));
328 // Embedded NULLs.
329 EXPECT_EQ(BASE_URL,
330 DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
331 BASE_URL "\0foo\0blat", kBaseUrlLen + 9));
334 #undef BASE_URL
336 } // namespace
338 } // namespace net