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

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

Powered by Google App Engine
This is Rietveld 408576698