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 |