This source file includes following definitions.
- TEST
- on_completion_is_error_
- RunTest
- RunTestWithCancel
- RunTestWithDeferredCancel
- OnCompletion
- OnTimeout
- OnCancelTimer
- WaitUntilDone
- FinishTestAllowCleanup
- TEST
- TEST
- ImplGetPacURLFromDhcp
- ImplCreateDhcpQuery
- ImplCreateAdapterFetcher
- TEST
- fetch_delay_ms_
- Fetch
- Cancel
- DidFinish
- GetResult
- GetPacScript
- OnTimer
- Configure
- ImplGetCandidateAdapterNames
- worker_finished_event_
- PushBackAdapter
- ConfigureAndPushBackAdapter
- ImplCreateAdapterFetcher
- ImplCreateAdapterQuery
- ImplGetMaxWait
- ImplOnGetCandidateAdapterNamesDone
- ResetTestState
- HasPendingFetchers
- result_
- RunTest
- RunMessageLoopUntilComplete
- RunMessageLoopUntilWorkerDone
- OnCompletion
- ResetTestState
- GetTaskRunner
- TestNormalCaseURLConfiguredOneAdapter
- TEST
- TestNormalCaseURLConfiguredMultipleAdapters
- TEST
- TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout
- TEST
- TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout
- TEST
- TestFailureCaseNoURLConfigured
- TEST
- TestFailureCaseNoDhcpAdapters
- TEST
- TestShortCircuitLessPreferredAdapters
- TEST
- TestImmediateCancel
- TEST
- TEST
#include "net/proxy/dhcp_proxy_script_fetcher_win.h"
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/timer/elapsed_timer.h"
#include "net/base/completion_callback.h"
#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
TEST(DhcpProxyScriptFetcherWin, AdapterNamesAndPacURLFromDhcp) {
std::set<std::string> adapter_names;
DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(&adapter_names);
for (std::set<std::string>::const_iterator it = adapter_names.begin();
it != adapter_names.end();
++it) {
const std::string& adapter_name = *it;
std::string pac_url =
DhcpProxyScriptAdapterFetcher::GetPacURLFromDhcp(adapter_name);
printf("Adapter '%s' has PAC URL '%s' configured in DHCP.\n",
adapter_name.c_str(),
pac_url.c_str());
}
}
class RealFetchTester {
public:
RealFetchTester()
: context_(new TestURLRequestContext),
fetcher_(new DhcpProxyScriptFetcherWin(context_.get())),
finished_(false),
on_completion_is_error_(false) {
timeout_.Start(FROM_HERE,
base::TimeDelta::FromSeconds(5), this, &RealFetchTester::OnTimeout);
}
void RunTest() {
int result = fetcher_->Fetch(
&pac_text_,
base::Bind(&RealFetchTester::OnCompletion, base::Unretained(this)));
if (result != ERR_IO_PENDING)
finished_ = true;
}
void RunTestWithCancel() {
RunTest();
fetcher_->Cancel();
}
void RunTestWithDeferredCancel() {
cancel_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(0),
this, &RealFetchTester::OnCancelTimer);
RunTest();
}
void OnCompletion(int result) {
if (on_completion_is_error_) {
FAIL() << "Received completion for test in which this is error.";
}
finished_ = true;
printf("Result code %d PAC data length %d\n", result, pac_text_.size());
}
void OnTimeout() {
printf("Timeout!");
OnCompletion(0);
}
void OnCancelTimer() {
fetcher_->Cancel();
finished_ = true;
}
void WaitUntilDone() {
while (!finished_) {
base::MessageLoop::current()->RunUntilIdle();
}
base::MessageLoop::current()->RunUntilIdle();
}
void FinishTestAllowCleanup() {
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
}
scoped_ptr<URLRequestContext> context_;
scoped_ptr<DhcpProxyScriptFetcherWin> fetcher_;
bool finished_;
base::string16 pac_text_;
base::OneShotTimer<RealFetchTester> timeout_;
base::OneShotTimer<RealFetchTester> cancel_timer_;
bool on_completion_is_error_;
};
TEST(DhcpProxyScriptFetcherWin, RealFetch) {
RealFetchTester fetcher;
fetcher.RunTest();
fetcher.WaitUntilDone();
printf("PAC URL was %s\n",
fetcher.fetcher_->GetPacURL().possibly_invalid_spec().c_str());
fetcher.FinishTestAllowCleanup();
}
TEST(DhcpProxyScriptFetcherWin, RealFetchWithCancel) {
RealFetchTester fetcher;
fetcher.RunTestWithCancel();
base::MessageLoop::current()->RunUntilIdle();
fetcher.FinishTestAllowCleanup();
}
class DelayingDhcpProxyScriptAdapterFetcher
: public DhcpProxyScriptAdapterFetcher {
public:
DelayingDhcpProxyScriptAdapterFetcher(
URLRequestContext* url_request_context,
scoped_refptr<base::TaskRunner> task_runner)
: DhcpProxyScriptAdapterFetcher(url_request_context, task_runner) {
}
class DelayingDhcpQuery : public DhcpQuery {
public:
explicit DelayingDhcpQuery()
: DhcpQuery() {
}
std::string ImplGetPacURLFromDhcp(
const std::string& adapter_name) OVERRIDE {
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
return DhcpQuery::ImplGetPacURLFromDhcp(adapter_name);
}
};
DhcpQuery* ImplCreateDhcpQuery() OVERRIDE {
return new DelayingDhcpQuery();
}
};
class DelayingDhcpProxyScriptFetcherWin
: public DhcpProxyScriptFetcherWin {
public:
explicit DelayingDhcpProxyScriptFetcherWin(
URLRequestContext* context)
: DhcpProxyScriptFetcherWin(context) {
}
DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE {
return new DelayingDhcpProxyScriptAdapterFetcher(url_request_context(),
GetTaskRunner());
}
};
TEST(DhcpProxyScriptFetcherWin, RealFetchWithDeferredCancel) {
RealFetchTester fetcher;
fetcher.fetcher_.reset(
new DelayingDhcpProxyScriptFetcherWin(fetcher.context_.get()));
fetcher.on_completion_is_error_ = true;
fetcher.RunTestWithDeferredCancel();
fetcher.WaitUntilDone();
}
class DummyDhcpProxyScriptAdapterFetcher
: public DhcpProxyScriptAdapterFetcher {
public:
DummyDhcpProxyScriptAdapterFetcher(URLRequestContext* context,
scoped_refptr<base::TaskRunner> runner)
: DhcpProxyScriptAdapterFetcher(context, runner),
did_finish_(false),
result_(OK),
pac_script_(L"bingo"),
fetch_delay_ms_(1) {
}
void Fetch(const std::string& adapter_name,
const CompletionCallback& callback) OVERRIDE {
callback_ = callback;
timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(fetch_delay_ms_),
this, &DummyDhcpProxyScriptAdapterFetcher::OnTimer);
}
void Cancel() OVERRIDE {
timer_.Stop();
}
bool DidFinish() const OVERRIDE {
return did_finish_;
}
int GetResult() const OVERRIDE {
return result_;
}
base::string16 GetPacScript() const OVERRIDE {
return pac_script_;
}
void OnTimer() {
callback_.Run(result_);
}
void Configure(bool did_finish,
int result,
base::string16 pac_script,
int fetch_delay_ms) {
did_finish_ = did_finish;
result_ = result;
pac_script_ = pac_script;
fetch_delay_ms_ = fetch_delay_ms;
}
private:
bool did_finish_;
int result_;
base::string16 pac_script_;
int fetch_delay_ms_;
CompletionCallback callback_;
base::OneShotTimer<DummyDhcpProxyScriptAdapterFetcher> timer_;
};
class MockDhcpProxyScriptFetcherWin : public DhcpProxyScriptFetcherWin {
public:
class MockAdapterQuery : public AdapterQuery {
public:
MockAdapterQuery() {
}
virtual ~MockAdapterQuery() {
}
virtual bool ImplGetCandidateAdapterNames(
std::set<std::string>* adapter_names) OVERRIDE {
adapter_names->insert(
mock_adapter_names_.begin(), mock_adapter_names_.end());
return true;
}
std::vector<std::string> mock_adapter_names_;
};
MockDhcpProxyScriptFetcherWin(URLRequestContext* context)
: DhcpProxyScriptFetcherWin(context),
num_fetchers_created_(0),
worker_finished_event_(true, false) {
ResetTestState();
}
virtual ~MockDhcpProxyScriptFetcherWin() {
ResetTestState();
}
using DhcpProxyScriptFetcherWin::GetTaskRunner;
void PushBackAdapter(const std::string& adapter_name,
DhcpProxyScriptAdapterFetcher* fetcher) {
adapter_query_->mock_adapter_names_.push_back(adapter_name);
adapter_fetchers_.push_back(fetcher);
}
void ConfigureAndPushBackAdapter(const std::string& adapter_name,
bool did_finish,
int result,
base::string16 pac_script,
base::TimeDelta fetch_delay) {
scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher(
new DummyDhcpProxyScriptAdapterFetcher(url_request_context(),
GetTaskRunner()));
adapter_fetcher->Configure(
did_finish, result, pac_script, fetch_delay.InMilliseconds());
PushBackAdapter(adapter_name, adapter_fetcher.release());
}
DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE {
++num_fetchers_created_;
return adapter_fetchers_[next_adapter_fetcher_index_++];
}
virtual AdapterQuery* ImplCreateAdapterQuery() OVERRIDE {
DCHECK(adapter_query_);
return adapter_query_.get();
}
base::TimeDelta ImplGetMaxWait() OVERRIDE {
return max_wait_;
}
void ImplOnGetCandidateAdapterNamesDone() OVERRIDE {
worker_finished_event_.Signal();
}
void ResetTestState() {
std::vector<DhcpProxyScriptAdapterFetcher*>::const_iterator it
= adapter_fetchers_.begin();
for (; it != adapter_fetchers_.end(); ++it) {
if (num_fetchers_created_-- <= 0) {
delete (*it);
}
}
next_adapter_fetcher_index_ = 0;
num_fetchers_created_ = 0;
adapter_fetchers_.clear();
adapter_query_ = new MockAdapterQuery();
max_wait_ = TestTimeouts::tiny_timeout();
}
bool HasPendingFetchers() {
return num_pending_fetchers() > 0;
}
int next_adapter_fetcher_index_;
std::vector<DhcpProxyScriptAdapterFetcher*> adapter_fetchers_;
scoped_refptr<MockAdapterQuery> adapter_query_;
base::TimeDelta max_wait_;
int num_fetchers_created_;
base::WaitableEvent worker_finished_event_;
};
class FetcherClient {
public:
FetcherClient()
: context_(new TestURLRequestContext),
fetcher_(context_.get()),
finished_(false),
result_(ERR_UNEXPECTED) {
}
void RunTest() {
int result = fetcher_.Fetch(
&pac_text_,
base::Bind(&FetcherClient::OnCompletion, base::Unretained(this)));
ASSERT_EQ(ERR_IO_PENDING, result);
}
void RunMessageLoopUntilComplete() {
while (!finished_) {
base::MessageLoop::current()->RunUntilIdle();
}
base::MessageLoop::current()->RunUntilIdle();
}
void RunMessageLoopUntilWorkerDone() {
DCHECK(fetcher_.adapter_query_.get());
while (!fetcher_.worker_finished_event_.TimedWait(
base::TimeDelta::FromMilliseconds(10))) {
base::MessageLoop::current()->RunUntilIdle();
}
}
void OnCompletion(int result) {
finished_ = true;
result_ = result;
}
void ResetTestState() {
finished_ = false;
result_ = ERR_UNEXPECTED;
pac_text_ = L"";
fetcher_.ResetTestState();
}
scoped_refptr<base::TaskRunner> GetTaskRunner() {
return fetcher_.GetTaskRunner();
}
scoped_ptr<URLRequestContext> context_;
MockDhcpProxyScriptFetcherWin fetcher_;
bool finished_;
int result_;
base::string16 pac_text_;
};
void TestNormalCaseURLConfiguredOneAdapter(FetcherClient* client) {
TestURLRequestContext context;
scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher(
new DummyDhcpProxyScriptAdapterFetcher(&context,
client->GetTaskRunner()));
adapter_fetcher->Configure(true, OK, L"bingo", 1);
client->fetcher_.PushBackAdapter("a", adapter_fetcher.release());
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_EQ(OK, client->result_);
ASSERT_EQ(L"bingo", client->pac_text_);
}
TEST(DhcpProxyScriptFetcherWin, NormalCaseURLConfiguredOneAdapter) {
FetcherClient client;
TestNormalCaseURLConfiguredOneAdapter(&client);
}
void TestNormalCaseURLConfiguredMultipleAdapters(FetcherClient* client) {
client->fetcher_.ConfigureAndPushBackAdapter(
"most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"second", true, OK, L"bingo", base::TimeDelta::FromMilliseconds(50));
client->fetcher_.ConfigureAndPushBackAdapter(
"third", true, OK, L"rocko", base::TimeDelta::FromMilliseconds(1));
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_EQ(OK, client->result_);
ASSERT_EQ(L"bingo", client->pac_text_);
}
TEST(DhcpProxyScriptFetcherWin, NormalCaseURLConfiguredMultipleAdapters) {
FetcherClient client;
TestNormalCaseURLConfiguredMultipleAdapters(&client);
}
void TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(
FetcherClient* client) {
client->fetcher_.ConfigureAndPushBackAdapter(
"most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"second", false, ERR_IO_PENDING, L"bingo",
TestTimeouts::action_timeout());
client->fetcher_.ConfigureAndPushBackAdapter(
"third", true, OK, L"rocko", base::TimeDelta::FromMilliseconds(1));
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_EQ(OK, client->result_);
ASSERT_EQ(L"rocko", client->pac_text_);
}
TEST(DhcpProxyScriptFetcherWin,
NormalCaseURLConfiguredMultipleAdaptersWithTimeout) {
FetcherClient client;
TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(&client);
}
void TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(
FetcherClient* client) {
client->fetcher_.ConfigureAndPushBackAdapter(
"most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"second", false, ERR_IO_PENDING, L"bingo",
TestTimeouts::action_timeout());
client->fetcher_.ConfigureAndPushBackAdapter(
"third", true, ERR_PAC_STATUS_NOT_OK, L"",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"fourth", true, ERR_NOT_IMPLEMENTED, L"",
base::TimeDelta::FromMilliseconds(1));
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_EQ(ERR_PAC_STATUS_NOT_OK, client->result_);
ASSERT_EQ(L"", client->pac_text_);
}
TEST(DhcpProxyScriptFetcherWin,
FailureCaseURLConfiguredMultipleAdaptersWithTimeout) {
FetcherClient client;
TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(&client);
}
void TestFailureCaseNoURLConfigured(FetcherClient* client) {
client->fetcher_.ConfigureAndPushBackAdapter(
"most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"second", false, ERR_IO_PENDING, L"bingo",
TestTimeouts::action_timeout());
client->fetcher_.ConfigureAndPushBackAdapter(
"third", true, ERR_PAC_NOT_IN_DHCP, L"",
base::TimeDelta::FromMilliseconds(1));
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_);
ASSERT_EQ(L"", client->pac_text_);
}
TEST(DhcpProxyScriptFetcherWin, FailureCaseNoURLConfigured) {
FetcherClient client;
TestFailureCaseNoURLConfigured(&client);
}
void TestFailureCaseNoDhcpAdapters(FetcherClient* client) {
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_);
ASSERT_EQ(L"", client->pac_text_);
ASSERT_EQ(0, client->fetcher_.num_fetchers_created_);
}
TEST(DhcpProxyScriptFetcherWin, FailureCaseNoDhcpAdapters) {
FetcherClient client;
TestFailureCaseNoDhcpAdapters(&client);
}
void TestShortCircuitLessPreferredAdapters(FetcherClient* client) {
client->fetcher_.ConfigureAndPushBackAdapter(
"1", true, ERR_PAC_NOT_IN_DHCP, L"",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"2", true, OK, L"bingo",
base::TimeDelta::FromMilliseconds(1));
client->fetcher_.ConfigureAndPushBackAdapter(
"3", true, OK, L"wrongo", TestTimeouts::action_max_timeout());
client->fetcher_.max_wait_ = TestTimeouts::action_timeout();
base::ElapsedTimer timer;
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_TRUE(client->fetcher_.HasPendingFetchers());
ASSERT_GT(client->fetcher_.max_wait_ - (client->fetcher_.max_wait_ / 10),
timer.Elapsed());
}
TEST(DhcpProxyScriptFetcherWin, ShortCircuitLessPreferredAdapters) {
FetcherClient client;
TestShortCircuitLessPreferredAdapters(&client);
}
void TestImmediateCancel(FetcherClient* client) {
TestURLRequestContext context;
scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher(
new DummyDhcpProxyScriptAdapterFetcher(&context,
client->GetTaskRunner()));
adapter_fetcher->Configure(true, OK, L"bingo", 1);
client->fetcher_.PushBackAdapter("a", adapter_fetcher.release());
client->RunTest();
client->fetcher_.Cancel();
client->RunMessageLoopUntilWorkerDone();
ASSERT_EQ(0, client->fetcher_.num_fetchers_created_);
}
TEST(DhcpProxyScriptFetcherWin, ImmediateCancel) {
FetcherClient client;
TestImmediateCancel(&client);
}
TEST(DhcpProxyScriptFetcherWin, ReuseFetcher) {
FetcherClient client;
typedef void (*FetcherClientTestFunction)(FetcherClient*);
typedef std::vector<FetcherClientTestFunction> TestVector;
TestVector test_functions;
test_functions.push_back(TestNormalCaseURLConfiguredOneAdapter);
test_functions.push_back(TestNormalCaseURLConfiguredMultipleAdapters);
test_functions.push_back(
TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout);
test_functions.push_back(
TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout);
test_functions.push_back(TestFailureCaseNoURLConfigured);
test_functions.push_back(TestFailureCaseNoDhcpAdapters);
test_functions.push_back(TestShortCircuitLessPreferredAdapters);
test_functions.push_back(TestImmediateCancel);
std::random_shuffle(test_functions.begin(),
test_functions.end(),
base::RandGenerator);
for (TestVector::const_iterator it = test_functions.begin();
it != test_functions.end();
++it) {
(*it)(&client);
client.ResetTestState();
}
(*test_functions.begin())(&client);
}
}
}