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.
5 #include "content/browser/resolve_proxy_msg_helper.h"
7 #include "content/browser/browser_thread_impl.h"
8 #include "content/common/view_messages.h"
9 #include "ipc/ipc_test_sink.h"
10 #include "net/base/net_errors.h"
11 #include "net/proxy/mock_proxy_resolver.h"
12 #include "net/proxy/proxy_config_service.h"
13 #include "net/proxy/proxy_service.h"
14 #include "testing/gtest/include/gtest/gtest.h"
18 // This ProxyConfigService always returns "http://pac" as the PAC url to use.
19 class MockProxyConfigService
: public net::ProxyConfigService
{
21 virtual void AddObserver(Observer
* observer
) OVERRIDE
{}
22 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{}
23 virtual ConfigAvailability
GetLatestProxyConfig(
24 net::ProxyConfig
* results
) OVERRIDE
{
25 *results
= net::ProxyConfig::CreateFromCustomPacURL(GURL("http://pac"));
30 class ResolveProxyMsgHelperTest
: public testing::Test
, public IPC::Listener
{
32 struct PendingResult
{
33 PendingResult(bool result
,
34 const std::string
& proxy_list
)
35 : result(result
), proxy_list(proxy_list
) {
39 std::string proxy_list
;
42 ResolveProxyMsgHelperTest()
43 : resolver_(new net::MockAsyncProxyResolver
),
45 new net::ProxyService(new MockProxyConfigService
, resolver_
, NULL
)),
46 helper_(new ResolveProxyMsgHelper(service_
.get())),
47 message_loop_(base::MessageLoop::TYPE_IO
),
48 io_thread_(BrowserThread::IO
, &message_loop_
) {
49 test_sink_
.AddFilter(this);
50 helper_
->OnFilterAdded(&test_sink_
);
54 const PendingResult
* pending_result() const { return pending_result_
.get(); }
56 void clear_pending_result() {
57 pending_result_
.reset();
60 IPC::Message
* GenerateReply() {
62 std::string temp_string
;
63 ViewHostMsg_ResolveProxy
message(GURL(), &temp_bool
, &temp_string
);
64 return IPC::SyncMessage::GenerateReply(&message
);
67 net::MockAsyncProxyResolver
* resolver_
;
68 scoped_ptr
<net::ProxyService
> service_
;
69 scoped_refptr
<ResolveProxyMsgHelper
> helper_
;
70 scoped_ptr
<PendingResult
> pending_result_
;
73 virtual bool OnMessageReceived(const IPC::Message
& msg
) OVERRIDE
{
74 TupleTypes
<ViewHostMsg_ResolveProxy::ReplyParam
>::ValueTuple reply_data
;
75 EXPECT_TRUE(ViewHostMsg_ResolveProxy::ReadReplyParam(&msg
, &reply_data
));
76 DCHECK(!pending_result_
.get());
77 pending_result_
.reset(new PendingResult(reply_data
.a
, reply_data
.b
));
78 test_sink_
.ClearMessages();
82 base::MessageLoop message_loop_
;
83 BrowserThreadImpl io_thread_
;
84 IPC::TestSink test_sink_
;
87 // Issue three sequential requests -- each should succeed.
88 TEST_F(ResolveProxyMsgHelperTest
, Sequential
) {
89 GURL
url1("http://www.google1.com/");
90 GURL
url2("http://www.google2.com/");
91 GURL
url3("http://www.google3.com/");
93 // Messages are deleted by the sink.
94 IPC::Message
* msg1
= GenerateReply();
95 IPC::Message
* msg2
= GenerateReply();
96 IPC::Message
* msg3
= GenerateReply();
98 // Execute each request sequentially (so there are never 2 requests
99 // outstanding at the same time).
101 helper_
->OnResolveProxy(url1
, msg1
);
103 // Finish ProxyService's initialization.
104 resolver_
->pending_set_pac_script_request()->CompleteNow(net::OK
);
106 ASSERT_EQ(1u, resolver_
->pending_requests().size());
107 EXPECT_EQ(url1
, resolver_
->pending_requests()[0]->url());
108 resolver_
->pending_requests()[0]->results()->UseNamedProxy("result1:80");
109 resolver_
->pending_requests()[0]->CompleteNow(net::OK
);
112 EXPECT_EQ(true, pending_result()->result
);
113 EXPECT_EQ("PROXY result1:80", pending_result()->proxy_list
);
114 clear_pending_result();
116 helper_
->OnResolveProxy(url2
, msg2
);
118 ASSERT_EQ(1u, resolver_
->pending_requests().size());
119 EXPECT_EQ(url2
, resolver_
->pending_requests()[0]->url());
120 resolver_
->pending_requests()[0]->results()->UseNamedProxy("result2:80");
121 resolver_
->pending_requests()[0]->CompleteNow(net::OK
);
124 EXPECT_EQ(true, pending_result()->result
);
125 EXPECT_EQ("PROXY result2:80", pending_result()->proxy_list
);
126 clear_pending_result();
128 helper_
->OnResolveProxy(url3
, msg3
);
130 ASSERT_EQ(1u, resolver_
->pending_requests().size());
131 EXPECT_EQ(url3
, resolver_
->pending_requests()[0]->url());
132 resolver_
->pending_requests()[0]->results()->UseNamedProxy("result3:80");
133 resolver_
->pending_requests()[0]->CompleteNow(net::OK
);
136 EXPECT_EQ(true, pending_result()->result
);
137 EXPECT_EQ("PROXY result3:80", pending_result()->proxy_list
);
138 clear_pending_result();
141 // Issue a request while one is already in progress -- should be queued.
142 TEST_F(ResolveProxyMsgHelperTest
, QueueRequests
) {
143 GURL
url1("http://www.google1.com/");
144 GURL
url2("http://www.google2.com/");
145 GURL
url3("http://www.google3.com/");
147 IPC::Message
* msg1
= GenerateReply();
148 IPC::Message
* msg2
= GenerateReply();
149 IPC::Message
* msg3
= GenerateReply();
151 // Start three requests. Since the proxy resolver is async, all the
152 // requests will be pending.
154 helper_
->OnResolveProxy(url1
, msg1
);
156 // Finish ProxyService's initialization.
157 resolver_
->pending_set_pac_script_request()->CompleteNow(net::OK
);
159 helper_
->OnResolveProxy(url2
, msg2
);
160 helper_
->OnResolveProxy(url3
, msg3
);
162 // ResolveProxyHelper only keeps 1 request outstanding in ProxyService
164 ASSERT_EQ(1u, resolver_
->pending_requests().size());
165 EXPECT_EQ(url1
, resolver_
->pending_requests()[0]->url());
167 resolver_
->pending_requests()[0]->results()->UseNamedProxy("result1:80");
168 resolver_
->pending_requests()[0]->CompleteNow(net::OK
);
171 EXPECT_EQ(true, pending_result()->result
);
172 EXPECT_EQ("PROXY result1:80", pending_result()->proxy_list
);
173 clear_pending_result();
175 ASSERT_EQ(1u, resolver_
->pending_requests().size());
176 EXPECT_EQ(url2
, resolver_
->pending_requests()[0]->url());
178 resolver_
->pending_requests()[0]->results()->UseNamedProxy("result2:80");
179 resolver_
->pending_requests()[0]->CompleteNow(net::OK
);
182 EXPECT_EQ(true, pending_result()->result
);
183 EXPECT_EQ("PROXY result2:80", pending_result()->proxy_list
);
184 clear_pending_result();
186 ASSERT_EQ(1u, resolver_
->pending_requests().size());
187 EXPECT_EQ(url3
, resolver_
->pending_requests()[0]->url());
189 resolver_
->pending_requests()[0]->results()->UseNamedProxy("result3:80");
190 resolver_
->pending_requests()[0]->CompleteNow(net::OK
);
193 EXPECT_EQ(true, pending_result()->result
);
194 EXPECT_EQ("PROXY result3:80", pending_result()->proxy_list
);
195 clear_pending_result();
198 // Delete the helper while a request is in progress, and others are pending.
199 TEST_F(ResolveProxyMsgHelperTest
, CancelPendingRequests
) {
200 GURL
url1("http://www.google1.com/");
201 GURL
url2("http://www.google2.com/");
202 GURL
url3("http://www.google3.com/");
204 // They will be deleted by the request's cancellation.
205 IPC::Message
* msg1
= GenerateReply();
206 IPC::Message
* msg2
= GenerateReply();
207 IPC::Message
* msg3
= GenerateReply();
209 // Start three requests. Since the proxy resolver is async, all the
210 // requests will be pending.
212 helper_
->OnResolveProxy(url1
, msg1
);
214 // Finish ProxyService's initialization.
215 resolver_
->pending_set_pac_script_request()->CompleteNow(net::OK
);
217 helper_
->OnResolveProxy(url2
, msg2
);
218 helper_
->OnResolveProxy(url3
, msg3
);
220 // ResolveProxyHelper only keeps 1 request outstanding in ProxyService
222 ASSERT_EQ(1u, resolver_
->pending_requests().size());
223 EXPECT_EQ(url1
, resolver_
->pending_requests()[0]->url());
225 // Delete the underlying ResolveProxyMsgHelper -- this should cancel all
226 // the requests which are outstanding.
229 // The pending requests sent to the proxy resolver should have been cancelled.
231 EXPECT_EQ(0u, resolver_
->pending_requests().size());
233 EXPECT_TRUE(pending_result() == NULL
);
235 // It should also be the case that msg1, msg2, msg3 were deleted by the
236 // cancellation. (Else will show up as a leak in Valgrind).
239 } // namespace content