Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc

Issue 6831025: Adds support for the DHCP portion of the WPAD (proxy auto-discovery) protocol. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix memory leaks in unit test. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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/synchronization/waitable_event.h"
9 #include "base/timer.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/proxy/mock_proxy_script_fetcher.h"
13 #include "net/proxy/proxy_script_fetcher_impl.h"
14 #include "net/test/test_server.h"
15 #include "net/url_request/url_request_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net {
19
20 namespace {
21
22 const char* const kPacUrl = "http://pacserver/script.pac";
23
24 // In net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc there are a few
25 // tests that exercise DhcpProxyScriptAdapterFetcher end-to-end along with
26 // DhcpProxyScriptFetcherWin, i.e. it tests the end-to-end usage of Win32
27 // APIs and the network. In this file we test only by stubbing out
28 // functionality.
29
30 // Version of DhcpProxyScriptAdapterFetcher that mocks out dependencies
31 // to allow unit testing.
32 class MockDhcpProxyScriptAdapterFetcher
33 : public DhcpProxyScriptAdapterFetcher {
34 public:
35 explicit MockDhcpProxyScriptAdapterFetcher(URLRequestContext* context)
36 : DhcpProxyScriptAdapterFetcher(context),
37 dhcp_delay_ms_(1),
38 timeout_ms_(100),
39 configured_url_(kPacUrl),
40 fetcher_delay_ms_(1),
41 fetcher_result_(OK),
42 pac_script_("bingo") {
43 }
44
45 void Cancel() {
46 DhcpProxyScriptAdapterFetcher::Cancel();
47 fetcher_ = NULL;
48 }
49
50 virtual ProxyScriptFetcher* ImplCreateScriptFetcher() OVERRIDE {
51 // We don't maintain ownership of the fetcher, it is transferred to
52 // the caller.
53 fetcher_ = new MockProxyScriptFetcher();
54 if (fetcher_delay_ms_ != -1) {
55 fetcher_timer_.Start(
56 base::TimeDelta::FromMilliseconds(fetcher_delay_ms_),
57 this, &MockDhcpProxyScriptAdapterFetcher::OnFetcherTimer);
58 }
59 return fetcher_;
60 }
61
62 class DelayingWorkerThread : public WorkerThread {
63 public:
64 explicit DelayingWorkerThread(
65 const base::WeakPtr<DhcpProxyScriptAdapterFetcher>& owner)
66 : WorkerThread(owner),
67 test_finished_event_(true, false) {
68 }
69
70 std::string ImplGetPacURLFromDhcp(
71 const std::string& adapter_name) OVERRIDE {
72 PerfTimer timer;
73 test_finished_event_.TimedWait(dhcp_delay_);
74 return configured_url_;
75 }
76
77 base::WaitableEvent test_finished_event_;
78 TimeDelta dhcp_delay_;
79 std::string configured_url_;
80 };
81
82 virtual WorkerThread* ImplCreateWorkerThread(
83 const base::WeakPtr<DhcpProxyScriptAdapterFetcher>& owner) OVERRIDE {
84 worker_thread_ = new DelayingWorkerThread(owner);
85 worker_thread_->dhcp_delay_ = TimeDelta::FromMilliseconds(dhcp_delay_ms_);
86 worker_thread_->configured_url_ = configured_url_;
87 return worker_thread_;
88 }
89
90 // Use a shorter timeout so tests can finish more quickly.
91 virtual base::TimeDelta ImplGetTimeout() const OVERRIDE {
92 return base::TimeDelta::FromMilliseconds(timeout_ms_);
93 }
94
95 void OnFetcherTimer() {
96 // Note that there is an assumption by this mock implementation that
97 // DhcpProxyScriptAdapterFetcher::Fetch will call ImplCreateScriptFetcher
98 // and call Fetch on the fetcher before the message loop is re-entered.
99 // This holds true today, but if you hit this DCHECK the problem can
100 // possibly be resolved by having a separate subclass of
101 // MockProxyScriptFetcher that adds the delay internally (instead of
102 // the simple approach currently used in ImplCreateScriptFetcher above).
103 DCHECK(fetcher_ && fetcher_->has_pending_request());
104 fetcher_->NotifyFetchCompletion(fetcher_result_, pac_script_);
105 fetcher_ = NULL;
106 }
107
108 bool IsWaitingForFetcher() const {
109 return state_ == STATE_WAIT_URL;
110 }
111
112 bool WasCancelled() const {
113 return state_ == STATE_CANCEL;
114 }
115
116 void FinishTest() {
117 DCHECK(worker_thread_);
118 worker_thread_->test_finished_event_.Signal();
119 }
120
121 int dhcp_delay_ms_;
122 int timeout_ms_;
123 std::string configured_url_;
124 int fetcher_delay_ms_;
125 int fetcher_result_;
126 std::string pac_script_;
127 MockProxyScriptFetcher* fetcher_;
128 base::OneShotTimer<MockDhcpProxyScriptAdapterFetcher> fetcher_timer_;
129 scoped_refptr<DelayingWorkerThread> worker_thread_;
130 };
131
132 class FetcherClient {
133 public:
134 FetcherClient()
135 : url_request_context_(new TestURLRequestContext()),
136 fetcher_(
137 new MockDhcpProxyScriptAdapterFetcher(url_request_context_.get())) {
138 }
139
140 void WaitForResult(int expected_error) {
141 EXPECT_EQ(expected_error, callback_.WaitForResult());
142 }
143
144 void RunTest() {
145 fetcher_->Fetch("adapter name", &callback_);
146 }
147
148 void FinishTestAllowCleanup() {
149 fetcher_->FinishTest();
150 MessageLoop::current()->RunAllPending();
151 }
152
153 TestCompletionCallback callback_;
154 scoped_refptr<URLRequestContext> url_request_context_;
155 scoped_ptr<MockDhcpProxyScriptAdapterFetcher> fetcher_;
156 string16 pac_text_;
157 };
158
159 TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLNotInDhcp) {
160 FetcherClient client;
161 client.fetcher_->configured_url_ = "";
162 client.RunTest();
163 client.WaitForResult(ERR_PAC_NOT_IN_DHCP);
164 ASSERT_TRUE(client.fetcher_->DidFinish());
165 EXPECT_EQ(ERR_PAC_NOT_IN_DHCP, client.fetcher_->GetResult());
166 EXPECT_EQ(string16(L""), client.fetcher_->GetPacScript());
167 }
168
169 TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLInDhcp) {
170 FetcherClient client;
171 client.RunTest();
172 client.WaitForResult(OK);
173 ASSERT_TRUE(client.fetcher_->DidFinish());
174 EXPECT_EQ(OK, client.fetcher_->GetResult());
175 EXPECT_EQ(string16(L"bingo"), client.fetcher_->GetPacScript());
176 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
177 }
178
179 TEST(DhcpProxyScriptAdapterFetcher, TimeoutDuringDhcp) {
180 // Does a Fetch() with a long enough delay on accessing DHCP that the
181 // fetcher should time out. This is to test a case manual testing found,
182 // where under certain circumstances (e.g. adapter enabled for DHCP and
183 // needs to retrieve its configuration from DHCP, but no DHCP server
184 // present on the network) accessing DHCP can take on the order of tens
185 // of seconds.
186 FetcherClient client;
187 client.fetcher_->dhcp_delay_ms_ = 20 * 1000;
188 client.fetcher_->timeout_ms_ = 25;
189
190 PerfTimer timer;
191 client.RunTest();
192 client.WaitForResult(ERR_TIMED_OUT);
193
194 // The timeout should occur within about 25 ms, way before the 20s set as
195 // the API delay above.
196 ASSERT_GT(base::TimeDelta::FromMilliseconds(35), timer.Elapsed());
197 ASSERT_TRUE(client.fetcher_->DidFinish());
198 EXPECT_EQ(ERR_TIMED_OUT, client.fetcher_->GetResult());
199 EXPECT_EQ(string16(L""), client.fetcher_->GetPacScript());
200 EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
201 client.FinishTestAllowCleanup();
202 }
203
204 TEST(DhcpProxyScriptAdapterFetcher, CancelWhileDhcp) {
205 FetcherClient client;
206 client.fetcher_->dhcp_delay_ms_ = 10;
207 client.RunTest();
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_->GetResult());
213 EXPECT_EQ(string16(L""), client.fetcher_->GetPacScript());
214 EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
215 client.FinishTestAllowCleanup();
216 }
217
218 TEST(DhcpProxyScriptAdapterFetcher, CancelWhileFetcher) {
219 FetcherClient client;
220 // This causes the mock fetcher not to pretend the
221 // fetcher finishes after a timeout.
222 client.fetcher_->fetcher_delay_ms_ = -1;
223 client.RunTest();
224 int max_loops = 4;
225 while (!client.fetcher_->IsWaitingForFetcher() && max_loops--) {
226 base::PlatformThread::Sleep(10);
227 MessageLoop::current()->RunAllPending();
228 }
229 client.fetcher_->Cancel();
230 MessageLoop::current()->RunAllPending();
231 ASSERT_FALSE(client.fetcher_->DidFinish());
232 ASSERT_TRUE(client.fetcher_->WasCancelled());
233 EXPECT_EQ(ERR_ABORTED, client.fetcher_->GetResult());
234 EXPECT_EQ(string16(L""), client.fetcher_->GetPacScript());
235 // GetPacURL() still returns the URL fetched in this case.
236 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
237 client.FinishTestAllowCleanup();
238 }
239
240 TEST(DhcpProxyScriptAdapterFetcher, CancelAtCompletion) {
241 FetcherClient client;
242 client.RunTest();
243 client.WaitForResult(OK);
244 client.fetcher_->Cancel();
245 // Canceling after you're done should have no effect, so these
246 // are identical expectations to the NormalCaseURLInDhcp test.
247 ASSERT_TRUE(client.fetcher_->DidFinish());
248 EXPECT_EQ(OK, client.fetcher_->GetResult());
249 EXPECT_EQ(string16(L"bingo"), client.fetcher_->GetPacScript());
250 EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
251 client.FinishTestAllowCleanup();
252 }
253
254 // Does a real fetch on a mock DHCP configuration.
255 class MockDhcpRealFetchProxyScriptAdapterFetcher
256 : public MockDhcpProxyScriptAdapterFetcher {
257 public:
258 explicit MockDhcpRealFetchProxyScriptAdapterFetcher(
259 URLRequestContext* context)
260 : MockDhcpProxyScriptAdapterFetcher(context),
261 url_request_context_(context) {
262 }
263
264 // Returns a real proxy script fetcher.
265 ProxyScriptFetcher* ImplCreateScriptFetcher() OVERRIDE {
266 ProxyScriptFetcher* fetcher =
267 new ProxyScriptFetcherImpl(url_request_context_);
268 return fetcher;
269 }
270
271 URLRequestContext* url_request_context_;
272 };
273
274 TEST(DhcpProxyScriptAdapterFetcher, MockDhcpRealFetch) {
275 TestServer test_server(
276 TestServer::TYPE_HTTP,
277 FilePath(FILE_PATH_LITERAL("net/data/proxy_script_fetcher_unittest")));
278 ASSERT_TRUE(test_server.Start());
279
280 GURL configured_url = test_server.GetURL("files/downloadable.pac");
281
282 FetcherClient client;
283 scoped_refptr<URLRequestContext> url_request_context(
284 new TestURLRequestContext());
285 client.fetcher_.reset(
286 new MockDhcpRealFetchProxyScriptAdapterFetcher(
287 url_request_context.get()));
288 client.fetcher_->configured_url_ = configured_url.spec();
289 client.RunTest();
290 client.WaitForResult(OK);
291 ASSERT_TRUE(client.fetcher_->DidFinish());
292 EXPECT_EQ(OK, client.fetcher_->GetResult());
293 EXPECT_EQ(string16(L"-downloadable.pac-\n"), client.fetcher_->GetPacScript());
294 EXPECT_EQ(configured_url,
295 client.fetcher_->GetPacURL());
296 }
297
298 } // namespace
299
300 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698