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_fetcher_win.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/message_loop.h" | |
10 #include "base/perftimer.h" | |
11 #include "base/rand_util.h" | |
12 #include "base/threading/platform_thread.h" | |
13 #include "net/base/completion_callback.h" | |
14 #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.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 TEST(WindowsDhcpProxyScriptFetcher, AdapterNamesAndPacURLFromDhcp) { | |
23 // This tests our core Win32 implementation without any of the wrappers | |
24 // we layer on top to achieve asynchronous and parallel operations. | |
25 // | |
26 // We don't make assumptions about the environment this unit test is | |
27 // running in, so it just exercises the code to make sure there | |
28 // is no crash and no error returned, but does not assert on the number | |
29 // of interfaces or the information returned via DHCP. | |
30 std::set<std::string> adapter_names; | |
31 WindowsDhcpProxyScriptFetcher::GetCandidateAdapterNames(&adapter_names); | |
32 for (std::set<std::string>::iterator it = adapter_names.begin(); | |
eroman
2011/05/17 04:39:39
nit: const_iterator ?
Jói
2011/05/17 15:38:35
Done.
| |
33 it != adapter_names.end(); | |
34 ++it) { | |
35 const std::string& adapter_name = *it; | |
36 std::string pac_url = | |
37 DhcpProxyScriptAdapterFetcher::GetPacURLFromDhcp(adapter_name); | |
38 printf("Adapter '%s' has PAC URL '%s' configured in DHCP.\n", | |
39 adapter_name.c_str(), | |
40 pac_url.c_str()); | |
41 } | |
42 } | |
43 | |
44 // Helper for RealFetch* tests below. | |
45 class RealFetchTester { | |
46 public: | |
47 RealFetchTester() | |
48 : context_((new TestURLRequestContext())), | |
49 fetcher_(new WindowsDhcpProxyScriptFetcher(context_.get())), | |
50 finished_(false), | |
51 ALLOW_THIS_IN_INITIALIZER_LIST( | |
52 completion_callback_(this, &RealFetchTester::OnCompletion)), | |
53 on_completion_is_error_(false) { | |
54 // Make sure the test ends. | |
55 timeout_.Start( | |
56 base::TimeDelta::FromSeconds(5), this, &RealFetchTester::OnTimeout); | |
57 } | |
58 | |
59 void RunTest() { | |
60 fetcher_->Fetch(&pac_text_, &completion_callback_); | |
61 } | |
62 | |
63 void RunTestWithCancel() { | |
64 RunTest(); | |
65 fetcher_->Cancel(); | |
66 } | |
67 | |
68 void RunTestWithDeferredCancel() { | |
69 RunTest(); | |
70 cancel_timer_.Start(base::TimeDelta::FromMilliseconds(1), | |
71 this, &RealFetchTester::OnCancelTimer); | |
72 } | |
73 | |
74 void OnCompletion(int result) { | |
75 if (on_completion_is_error_) { | |
76 FAIL() << "Received completion for test in which this is error."; | |
77 } | |
78 finished_ = true; | |
79 printf("Result code %d PAC data length %d\n", result, pac_text_.size()); | |
80 } | |
81 | |
82 void OnTimeout() { | |
83 printf("Timeout!"); | |
84 OnCompletion(0); | |
85 } | |
86 | |
87 void OnCancelTimer() { | |
88 fetcher_->Cancel(); | |
89 finished_ = true; | |
90 } | |
91 | |
92 void WaitUntilDone() { | |
93 while (!finished_) { | |
94 MessageLoop::current()->RunAllPending(); | |
95 } | |
96 MessageLoop::current()->RunAllPending(); | |
97 } | |
98 | |
99 // Attempts to give worker threads time to finish. This is currently | |
100 // very simplistic as completion (via completion callback or cancellation) | |
101 // immediately "detaches" any worker threads, so the best we can do is give | |
102 // them a little time. If we start running into Valgrind leaks, we can | |
103 // do something a bit more clever to track worker threads even when the | |
104 // WindowsDhcpProxyScriptFetcher state machine has finished. | |
105 void FinishTestAllowCleanup() { | |
106 base::PlatformThread::Sleep(30); | |
107 } | |
108 | |
109 scoped_refptr<URLRequestContext> context_; | |
110 scoped_ptr<WindowsDhcpProxyScriptFetcher> fetcher_; | |
111 bool finished_; | |
112 string16 pac_text_; | |
113 CompletionCallbackImpl<RealFetchTester> completion_callback_; | |
114 base::OneShotTimer<RealFetchTester> timeout_; | |
115 base::OneShotTimer<RealFetchTester> cancel_timer_; | |
116 bool on_completion_is_error_; | |
117 }; | |
118 | |
119 TEST(WindowsDhcpProxyScriptFetcher, RealFetch) { | |
120 // This tests a call to Fetch() with no stubbing out of dependencies. | |
121 // | |
122 // We don't make assumptions about the environment this unit test is | |
123 // running in, so it just exercises the code to make sure there | |
124 // is no crash and no unexpected error returned, but does not assert on | |
125 // results beyond that. | |
126 RealFetchTester fetcher; | |
127 fetcher.RunTest(); | |
128 | |
129 fetcher.WaitUntilDone(); | |
130 printf("PAC URL was %s\n", | |
131 fetcher.fetcher_->GetPacURL().possibly_invalid_spec().c_str()); | |
132 | |
133 fetcher.FinishTestAllowCleanup(); | |
134 } | |
135 | |
136 TEST(WindowsDhcpProxyScriptFetcher, RealFetchWithCancel) { | |
137 // Does a Fetch() with an immediate cancel. As before, just | |
138 // exercises the code without stubbing out dependencies. | |
139 RealFetchTester fetcher; | |
140 fetcher.RunTestWithCancel(); | |
141 MessageLoop::current()->RunAllPending(); | |
142 | |
143 // Attempt to avoid Valgrind leak reports in case worker thread is | |
144 // still running. | |
145 fetcher.FinishTestAllowCleanup(); | |
146 } | |
147 | |
148 // For RealFetchWithDeferredCancel, below. | |
149 class DelayingDhcpProxyScriptAdapterFetcher | |
150 : public DhcpProxyScriptAdapterFetcher { | |
151 public: | |
152 explicit DelayingDhcpProxyScriptAdapterFetcher( | |
153 URLRequestContext* url_request_context) | |
154 : DhcpProxyScriptAdapterFetcher(url_request_context) { | |
155 } | |
156 | |
157 class DelayingWorkerThread : public WorkerThread { | |
158 public: | |
159 explicit DelayingWorkerThread( | |
160 const base::WeakPtr<DhcpProxyScriptAdapterFetcher>& owner) | |
161 : WorkerThread(owner) { | |
162 } | |
163 | |
164 std::string ImplGetPacURLFromDhcp( | |
165 const std::string& adapter_name) OVERRIDE { | |
166 base::PlatformThread::Sleep(20); | |
167 return WorkerThread::ImplGetPacURLFromDhcp(adapter_name); | |
168 } | |
169 }; | |
170 | |
171 WorkerThread* ImplCreateWorkerThread( | |
172 const base::WeakPtr<DhcpProxyScriptAdapterFetcher>& owner) OVERRIDE { | |
173 return new DelayingWorkerThread(owner); | |
174 } | |
175 }; | |
176 | |
177 // For RealFetchWithDeferredCancel, below. | |
178 class DelayingWindowsDhcpProxyScriptFetcher | |
179 : public WindowsDhcpProxyScriptFetcher { | |
180 public: | |
181 explicit DelayingWindowsDhcpProxyScriptFetcher( | |
182 URLRequestContext* context) | |
183 : WindowsDhcpProxyScriptFetcher(context) { | |
184 } | |
185 | |
186 DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE { | |
187 return new DelayingDhcpProxyScriptAdapterFetcher(url_request_context_); | |
188 } | |
189 }; | |
190 | |
191 TEST(WindowsDhcpProxyScriptFetcher, RealFetchWithDeferredCancel) { | |
192 // Does a Fetch() with a slightly delayed cancel. As before, just | |
193 // exercises the code without stubbing out dependencies, but | |
194 // introduces a guaranteed 20 ms delay on the worker threads so that | |
195 // the cancel is called before they complete. | |
196 RealFetchTester fetcher; | |
197 fetcher.fetcher_.reset( | |
198 new DelayingWindowsDhcpProxyScriptFetcher(fetcher.context_)); | |
199 fetcher.on_completion_is_error_ = true; | |
200 fetcher.RunTestWithDeferredCancel(); | |
201 fetcher.WaitUntilDone(); | |
202 } | |
203 | |
204 // The remaining tests are to exercise our state machine in various | |
205 // situations, with actual network access fully stubbed out. | |
206 | |
207 class DummyDhcpProxyScriptAdapterFetcher | |
208 : public DhcpProxyScriptAdapterFetcher { | |
209 public: | |
210 DummyDhcpProxyScriptAdapterFetcher() | |
211 : DhcpProxyScriptAdapterFetcher(new TestURLRequestContext()), | |
212 did_finish_(false), | |
213 result_(OK), | |
214 pac_script_(L"bingo"), | |
215 fetch_delay_ms_(1), | |
216 client_callback_(NULL) { | |
217 } | |
218 | |
219 void Fetch(const std::string& adapter_name, | |
220 CompletionCallback* callback) OVERRIDE { | |
221 client_callback_ = callback; | |
222 timer_.Start(base::TimeDelta::FromMilliseconds(fetch_delay_ms_), | |
223 this, &DummyDhcpProxyScriptAdapterFetcher::OnTimer); | |
224 } | |
225 | |
226 void Cancel() OVERRIDE { | |
227 timer_.Stop(); | |
228 } | |
229 | |
230 bool DidFinish() const OVERRIDE { | |
231 return did_finish_; | |
232 } | |
233 | |
234 int GetResult() const OVERRIDE { | |
235 return result_; | |
236 } | |
237 | |
238 string16 GetPacScript() const OVERRIDE { | |
239 return pac_script_; | |
240 } | |
241 | |
242 void OnTimer() { | |
243 client_callback_->Run(result_); | |
244 } | |
245 | |
246 void Configure( | |
247 bool did_finish, int result, string16 pac_script, int fetch_delay_ms) { | |
248 did_finish_ = did_finish; | |
249 result_ = result; | |
250 pac_script_ = pac_script; | |
251 fetch_delay_ms_ = fetch_delay_ms; | |
252 } | |
253 | |
254 private: | |
255 bool did_finish_; | |
256 int result_; | |
257 string16 pac_script_; | |
258 int fetch_delay_ms_; | |
259 CompletionCallback* client_callback_; | |
260 base::OneShotTimer<DummyDhcpProxyScriptAdapterFetcher> timer_; | |
261 }; | |
262 | |
263 class MockWindowsDhcpProxyScriptFetcher : public WindowsDhcpProxyScriptFetcher { | |
264 public: | |
265 MockWindowsDhcpProxyScriptFetcher() | |
266 : WindowsDhcpProxyScriptFetcher(new TestURLRequestContext()), | |
267 next_adapter_fetcher_index_(0) { | |
268 } | |
269 | |
270 // Adds a fetcher object to the queue of fetchers used by | |
271 // |ImplCreateAdapterFetcher()|, and its name to the list of adapters | |
272 // returned by ImplGetCandidateAdapterNames. | |
273 void PushBackAdapter(const std::string& adapter_name, | |
274 DhcpProxyScriptAdapterFetcher* fetcher) { | |
275 adapter_names_.push_back(adapter_name); | |
276 adapter_fetchers_.push_back(fetcher); | |
277 } | |
278 | |
279 void ConfigureAndPushBackAdapter(const std::string& adapter_name, | |
280 bool did_finish, | |
281 int result, | |
282 string16 pac_script, | |
283 int fetch_delay_ms) { | |
284 scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher( | |
285 new DummyDhcpProxyScriptAdapterFetcher()); | |
286 adapter_fetcher->Configure(did_finish, result, pac_script, fetch_delay_ms); | |
287 PushBackAdapter(adapter_name, adapter_fetcher.release()); | |
288 } | |
289 | |
290 DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE { | |
291 return adapter_fetchers_[next_adapter_fetcher_index_++]; | |
292 } | |
293 | |
294 bool ImplGetCandidateAdapterNames( | |
295 std::set<std::string>* adapter_names) OVERRIDE { | |
296 adapter_names->insert(adapter_names_.begin(), adapter_names_.end()); | |
297 return true; | |
298 } | |
299 | |
300 int ImplGetMaxWaitMs() OVERRIDE { | |
301 return 25; | |
302 } | |
303 | |
304 void ResetTestState() { | |
305 next_adapter_fetcher_index_ = 0; | |
306 adapter_fetchers_.clear(); | |
307 // String pointers contained herein will have been freed during test. | |
308 adapter_names_.clear(); | |
309 } | |
310 | |
311 int next_adapter_fetcher_index_; | |
312 | |
313 // Ownership is not here; it gets transferred to the implementation | |
314 // class via ImplCreateAdapterFetcher. | |
315 std::vector<DhcpProxyScriptAdapterFetcher*> adapter_fetchers_; | |
316 | |
317 std::vector<std::string> adapter_names_; | |
318 }; | |
319 | |
320 class FetcherClient { | |
321 public: | |
322 FetcherClient() | |
323 : finished_(false), | |
324 result_(ERR_UNEXPECTED), | |
325 ALLOW_THIS_IN_INITIALIZER_LIST( | |
326 completion_callback_(this, &FetcherClient::OnCompletion)) { | |
327 } | |
328 | |
329 void RunTest() { | |
330 int result = fetcher_.Fetch(&pac_text_, &completion_callback_); | |
331 ASSERT_EQ(ERR_IO_PENDING, result); | |
332 } | |
333 | |
334 void RunImmediateReturnTest() { | |
335 int result = fetcher_.Fetch(&pac_text_, &completion_callback_); | |
336 ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, result); | |
337 } | |
338 | |
339 void RunMessageLoopUntilComplete() { | |
340 while (!finished_) { | |
341 MessageLoop::current()->RunAllPending(); | |
342 } | |
343 MessageLoop::current()->RunAllPending(); | |
344 } | |
345 | |
346 void OnCompletion(int result) { | |
347 finished_ = true; | |
348 result_ = result; | |
349 } | |
350 | |
351 void ResetTestState() { | |
352 finished_ = false; | |
353 result_ = ERR_UNEXPECTED; | |
354 pac_text_ = L""; | |
355 fetcher_.ResetTestState(); | |
356 } | |
357 | |
358 MockWindowsDhcpProxyScriptFetcher fetcher_; | |
359 bool finished_; | |
360 int result_; | |
361 string16 pac_text_; | |
362 CompletionCallbackImpl<FetcherClient> completion_callback_; | |
363 }; | |
364 | |
365 // We separate out each test's logic so that we can easily implement | |
366 // the ReuseFetcher test at the bottom. | |
367 void TestNormalCaseURLConfiguredOneAdapter(FetcherClient* client) { | |
368 scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher( | |
369 new DummyDhcpProxyScriptAdapterFetcher()); | |
370 adapter_fetcher->Configure(true, OK, L"bingo", 1); | |
371 client->fetcher_.PushBackAdapter("a", adapter_fetcher.release()); | |
372 client->RunTest(); | |
373 client->RunMessageLoopUntilComplete(); | |
374 ASSERT_EQ(OK, client->result_); | |
375 ASSERT_EQ(L"bingo", client->pac_text_); | |
376 } | |
377 | |
378 TEST(WindowsDhcpProxyScriptFetcher, NormalCaseURLConfiguredOneAdapter) { | |
379 FetcherClient client; | |
380 TestNormalCaseURLConfiguredOneAdapter(&client); | |
381 } | |
382 | |
383 void TestNormalCaseURLConfiguredMultipleAdapters(FetcherClient* client) { | |
384 client->fetcher_.ConfigureAndPushBackAdapter( | |
385 "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"", 1); | |
386 client->fetcher_.ConfigureAndPushBackAdapter( | |
387 "second", true, OK, L"bingo", 50); | |
388 client->fetcher_.ConfigureAndPushBackAdapter( | |
389 "third", true, OK, L"rocko", 1); | |
390 client->RunTest(); | |
391 client->RunMessageLoopUntilComplete(); | |
392 ASSERT_EQ(OK, client->result_); | |
393 ASSERT_EQ(L"bingo", client->pac_text_); | |
394 } | |
395 | |
396 TEST(WindowsDhcpProxyScriptFetcher, NormalCaseURLConfiguredMultipleAdapters) { | |
397 FetcherClient client; | |
398 TestNormalCaseURLConfiguredMultipleAdapters(&client); | |
399 } | |
400 | |
401 void TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout( | |
402 FetcherClient* client) { | |
403 client->fetcher_.ConfigureAndPushBackAdapter( | |
404 "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"", 1); | |
405 // This will time out. | |
406 client->fetcher_.ConfigureAndPushBackAdapter( | |
407 "second", false, ERR_IO_PENDING, L"bingo", 1000); | |
408 client->fetcher_.ConfigureAndPushBackAdapter( | |
409 "third", true, OK, L"rocko", 1); | |
410 client->RunTest(); | |
411 client->RunMessageLoopUntilComplete(); | |
412 ASSERT_EQ(OK, client->result_); | |
413 ASSERT_EQ(L"rocko", client->pac_text_); | |
414 } | |
415 | |
416 TEST(WindowsDhcpProxyScriptFetcher, | |
417 NormalCaseURLConfiguredMultipleAdaptersWithTimeout) { | |
418 FetcherClient client; | |
419 TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(&client); | |
420 } | |
421 | |
422 void TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout( | |
423 FetcherClient* client) { | |
424 client->fetcher_.ConfigureAndPushBackAdapter( | |
425 "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"", 1); | |
426 // This will time out. | |
427 client->fetcher_.ConfigureAndPushBackAdapter( | |
428 "second", false, ERR_IO_PENDING, L"bingo", 1000); | |
429 // This is the first non-ERR_PAC_NOT_IN_DHCP error and as such | |
430 // should be chosen. | |
431 client->fetcher_.ConfigureAndPushBackAdapter( | |
432 "third", true, ERR_PAC_STATUS_NOT_OK, L"", 1); | |
433 client->fetcher_.ConfigureAndPushBackAdapter( | |
434 "fourth", true, ERR_NOT_IMPLEMENTED, L"", 1); | |
435 client->RunTest(); | |
436 client->RunMessageLoopUntilComplete(); | |
437 ASSERT_EQ(ERR_PAC_STATUS_NOT_OK, client->result_); | |
438 ASSERT_EQ(L"", client->pac_text_); | |
439 } | |
440 | |
441 TEST(WindowsDhcpProxyScriptFetcher, | |
442 FailureCaseURLConfiguredMultipleAdaptersWithTimeout) { | |
443 FetcherClient client; | |
444 TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(&client); | |
445 } | |
446 | |
447 void TestFailureCaseNoURLConfigured(FetcherClient* client) { | |
448 client->fetcher_.ConfigureAndPushBackAdapter( | |
449 "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"", 1); | |
450 // This will time out. | |
451 client->fetcher_.ConfigureAndPushBackAdapter( | |
452 "second", false, ERR_IO_PENDING, L"bingo", 1000); | |
453 // This is the first non-ERR_PAC_NOT_IN_DHCP error and as such | |
454 // should be chosen. | |
455 client->fetcher_.ConfigureAndPushBackAdapter( | |
456 "third", true, ERR_PAC_NOT_IN_DHCP, L"", 1); | |
457 client->RunTest(); | |
458 client->RunMessageLoopUntilComplete(); | |
459 ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_); | |
460 ASSERT_EQ(L"", client->pac_text_); | |
461 } | |
462 | |
463 TEST(WindowsDhcpProxyScriptFetcher, FailureCaseNoURLConfigured) { | |
464 FetcherClient client; | |
465 TestFailureCaseNoURLConfigured(&client); | |
466 } | |
467 | |
468 void TestFailureCaseNoDhcpAdapters(FetcherClient* client) { | |
469 client->RunImmediateReturnTest(); | |
470 // In case there are any pending messages that get us in a bad state | |
471 // (there shouldn't be). | |
472 MessageLoop::current()->RunAllPending(); | |
473 } | |
474 | |
475 TEST(WindowsDhcpProxyScriptFetcher, FailureCaseNoDhcpAdapters) { | |
476 FetcherClient client; | |
477 TestFailureCaseNoDhcpAdapters(&client); | |
478 } | |
479 | |
480 void TestShortCircuitLessPreferredAdapters(FetcherClient* client) { | |
eroman
2011/05/17 04:39:39
I did not have time to review this file thoroughly
Jói
2011/05/17 15:38:35
OK, thanks Eric.
| |
481 // Here we have a bunch of adapters; the first reports no PAC in DHCP, | |
482 // the second responds quickly with a PAC file, the rest take a long | |
483 // time. Verify that we complete quickly and do not wait for the slow | |
484 // adapters, i.e. we finish before timeout. | |
485 client->fetcher_.ConfigureAndPushBackAdapter( | |
486 "1", true, ERR_PAC_NOT_IN_DHCP, L"", 1); | |
487 client->fetcher_.ConfigureAndPushBackAdapter( | |
488 "2", true, OK, L"bingo", 1); | |
489 client->fetcher_.ConfigureAndPushBackAdapter( | |
490 "3", true, OK, L"wrongo", 1000); | |
491 | |
492 PerfTimer timer; | |
493 client->RunTest(); | |
494 client->RunMessageLoopUntilComplete(); | |
495 // Assert that the time passed is just less than the wait timer | |
496 // timeout (which we have mocked out above to be 25 ms), to avoid | |
497 // flakiness but still get a strong signal that it was the shortcut | |
498 // mechanism (in OnFetcherDone) that kicked in. | |
499 ASSERT_GT(TimeDelta::FromMilliseconds(23), timer.Elapsed()); | |
500 } | |
501 | |
502 TEST(WindowsDhcpProxyScriptFetcher, ShortCircuitLessPreferredAdapters) { | |
503 FetcherClient client; | |
504 TestShortCircuitLessPreferredAdapters(&client); | |
505 } | |
506 | |
507 TEST(WindowsDhcpProxyScriptFetcher, ReuseFetcher) { | |
508 FetcherClient client; | |
509 | |
510 // The ProxyScriptFetcher interface stipulates that only a single | |
511 // |Fetch()| may be in flight at once, but allows reuse, so test | |
512 // that the state transitions correctly from done to start in all | |
513 // cases we're testing. | |
514 | |
515 typedef void (*FetcherClientTestFunction)(FetcherClient*); | |
516 typedef std::vector<FetcherClientTestFunction> TestVector; | |
517 TestVector test_functions; | |
518 test_functions.push_back(TestNormalCaseURLConfiguredOneAdapter); | |
519 test_functions.push_back(TestNormalCaseURLConfiguredMultipleAdapters); | |
520 test_functions.push_back( | |
521 TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout); | |
522 test_functions.push_back( | |
523 TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout); | |
524 test_functions.push_back(TestFailureCaseNoURLConfigured); | |
525 test_functions.push_back(TestFailureCaseNoDhcpAdapters); | |
526 test_functions.push_back(TestShortCircuitLessPreferredAdapters); | |
527 | |
528 std::random_shuffle(test_functions.begin(), | |
529 test_functions.end(), | |
530 base::RandGenerator); | |
531 for (TestVector::iterator it = test_functions.begin(); | |
532 it != test_functions.end(); | |
533 ++it) { | |
534 (*it)(&client); | |
535 client.ResetTestState(); | |
536 } | |
537 | |
538 // Re-do the first test to make sure the last test that was run did | |
539 // not leave things in a bad state. | |
540 (*test_functions.begin())(&client); | |
541 } | |
542 | |
543 } // namespace | |
544 | |
545 } // namespace net | |
OLD | NEW |