Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / proxy / dhcp_proxy_script_adapter_fetcher_win_unittest.cc
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.
4
5 #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
6
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"
19
20 namespace net {
21
22 namespace {
23
24 const char* const kPacUrl = "http://pacserver/script.pac";
25
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.
31
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") {
47   }
48
49   void Cancel() {
50     DhcpProxyScriptAdapterFetcher::Cancel();
51     fetcher_ = NULL;
52   }
53
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);
62     }
63     return fetcher_;
64   }
65
66   class DelayingDhcpQuery : public DhcpQuery {
67    public:
68     explicit DelayingDhcpQuery()
69         : DhcpQuery(),
70           test_finished_event_(true, false) {
71     }
72
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_;
78     }
79
80     base::WaitableEvent test_finished_event_;
81     base::TimeDelta dhcp_delay_;
82     std::string configured_url_;
83   };
84
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_;
90   }
91
92   // Use a shorter timeout so tests can finish more quickly.
93   virtual base::TimeDelta ImplGetTimeout() const override {
94     return timeout_;
95   }
96
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;
108   }
109
110   bool IsWaitingForFetcher() const {
111     return state() == STATE_WAIT_URL;
112   }
113
114   bool WasCancelled() const {
115     return state() == STATE_CANCEL;
116   }
117
118   void FinishTest() {
119     DCHECK(dhcp_query_);
120     dhcp_query_->test_finished_event_.Signal();
121   }
122
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_;
132 };
133
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))) {
144   }
145
146   ~FetcherClient() {
147     worker_pool_->Shutdown();
148   }
149
150   void WaitForResult(int expected_error) {
151     EXPECT_EQ(expected_error, callback_.WaitForResult());
152   }
153
154   void RunTest() {
155     fetcher_->Fetch("adapter name", callback_.callback());
156   }
157
158   void FinishTestAllowCleanup() {
159     fetcher_->FinishTest();
160     base::MessageLoop::current()->RunUntilIdle();
161   }
162
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_;
168 };
169
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());
178 }
179
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());
188 }
189
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);
200
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);
206
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();
212 }
213
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();
225 }
226
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();
237   }
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();
247 }
248
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();
261 }
262
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) {
272   }
273
274   // Returns a real proxy script fetcher.
275   ProxyScriptFetcher* ImplCreateScriptFetcher() override {
276     ProxyScriptFetcher* fetcher =
277         new ProxyScriptFetcherImpl(url_request_context_);
278     return fetcher;
279   }
280
281   URLRequestContext* url_request_context_;
282 };
283
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());
291
292   GURL configured_url = test_server.GetURL("files/downloadable.pac");
293
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());
311 }
312
313 #define BASE_URL "http://corpserver/proxy.pac"
314
315 TEST(DhcpProxyScriptAdapterFetcher, SanitizeDhcpApiString) {
316   const size_t kBaseUrlLen = strlen(BASE_URL);
317
318   // Default case.
319   EXPECT_EQ(BASE_URL,
320             DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
321                 BASE_URL, kBaseUrlLen));
322
323   // Trailing \n and no null-termination.
324   EXPECT_EQ(BASE_URL,
325             DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
326                 BASE_URL "\nblablabla", kBaseUrlLen + 1));
327
328   // Embedded NULLs.
329   EXPECT_EQ(BASE_URL,
330             DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
331                 BASE_URL "\0foo\0blat", kBaseUrlLen + 9));
332 }
333
334 #undef BASE_URL
335
336 }  // namespace
337
338 }  // namespace net