1 // Copyright (c) 2012 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 "chrome/browser/net/http_server_properties_manager.h"
7 #include "base/basictypes.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/values.h"
12 #include "chrome/common/pref_names.h"
13 #include "content/public/test/test_browser_thread.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
18 namespace chrome_browser_net
{
23 using ::testing::Invoke
;
24 using ::testing::Mock
;
25 using ::testing::StrictMock
;
26 using content::BrowserThread
;
28 class TestingHttpServerPropertiesManager
: public HttpServerPropertiesManager
{
30 explicit TestingHttpServerPropertiesManager(PrefService
* pref_service
)
31 : HttpServerPropertiesManager(pref_service
) {
32 InitializeOnIOThread();
35 virtual ~TestingHttpServerPropertiesManager() {
38 // Make these methods public for testing.
39 using HttpServerPropertiesManager::ScheduleUpdateCacheOnUI
;
40 using HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO
;
42 // Post tasks without a delay during tests.
43 virtual void StartPrefsUpdateTimerOnIO(base::TimeDelta delay
) OVERRIDE
{
44 HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO(
48 void UpdateCacheFromPrefsOnUIConcrete() {
49 HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI();
52 // Post tasks without a delay during tests.
53 virtual void StartCacheUpdateTimerOnUI(base::TimeDelta delay
) OVERRIDE
{
54 HttpServerPropertiesManager::StartCacheUpdateTimerOnUI(
58 void UpdatePrefsFromCacheOnIOConcrete(const base::Closure
& callback
) {
59 HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO(callback
);
62 MOCK_METHOD0(UpdateCacheFromPrefsOnUI
, void());
63 MOCK_METHOD1(UpdatePrefsFromCacheOnIO
, void(const base::Closure
&));
64 MOCK_METHOD5(UpdateCacheFromPrefsOnIO
,
65 void(std::vector
<std::string
>* spdy_servers
,
66 net::SpdySettingsMap
* spdy_settings_map
,
67 net::AlternateProtocolMap
* alternate_protocol_map
,
68 net::PipelineCapabilityMap
* pipeline_capability_map
,
69 bool detected_corrupted_prefs
));
70 MOCK_METHOD4(UpdatePrefsOnUI
,
71 void(base::ListValue
* spdy_server_list
,
72 net::SpdySettingsMap
* spdy_settings_map
,
73 net::AlternateProtocolMap
* alternate_protocol_map
,
74 net::PipelineCapabilityMap
* pipeline_capability_map
));
77 DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager
);
80 class HttpServerPropertiesManagerTest
: public testing::Test
{
82 HttpServerPropertiesManagerTest()
83 : ui_thread_(BrowserThread::UI
, &loop_
),
84 io_thread_(BrowserThread::IO
, &loop_
) {
87 virtual void SetUp() OVERRIDE
{
88 pref_service_
.registry()->RegisterDictionaryPref(
89 prefs::kHttpServerProperties
);
90 http_server_props_manager_
.reset(
91 new StrictMock
<TestingHttpServerPropertiesManager
>(&pref_service_
));
96 virtual void TearDown() OVERRIDE
{
97 if (http_server_props_manager_
.get())
98 http_server_props_manager_
->ShutdownOnUIThread();
100 // Delete |http_server_props_manager_| while |io_thread_| is mapping IO to
102 http_server_props_manager_
.reset();
105 void ExpectCacheUpdate() {
106 EXPECT_CALL(*http_server_props_manager_
, UpdateCacheFromPrefsOnUI())
108 Invoke(http_server_props_manager_
.get(),
109 &TestingHttpServerPropertiesManager::
110 UpdateCacheFromPrefsOnUIConcrete
));
113 void ExpectPrefsUpdate() {
114 EXPECT_CALL(*http_server_props_manager_
, UpdatePrefsFromCacheOnIO(_
))
116 Invoke(http_server_props_manager_
.get(),
117 &TestingHttpServerPropertiesManager::
118 UpdatePrefsFromCacheOnIOConcrete
));
121 void ExpectPrefsUpdateRepeatedly() {
122 EXPECT_CALL(*http_server_props_manager_
, UpdatePrefsFromCacheOnIO(_
))
124 Invoke(http_server_props_manager_
.get(),
125 &TestingHttpServerPropertiesManager::
126 UpdatePrefsFromCacheOnIOConcrete
));
129 base::MessageLoop loop_
;
130 TestingPrefServiceSimple pref_service_
;
131 scoped_ptr
<TestingHttpServerPropertiesManager
> http_server_props_manager_
;
134 content::TestBrowserThread ui_thread_
;
135 content::TestBrowserThread io_thread_
;
137 DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest
);
140 TEST_F(HttpServerPropertiesManagerTest
,
141 SingleUpdateForTwoSpdyServerPrefChanges
) {
144 // Set up the prefs for www.google.com:80 and mail.google.com:80 and then set
145 // it twice. Only expect a single cache update.
147 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
149 // Set supports_spdy for www.google.com:80.
150 server_pref_dict
->SetBoolean("supports_spdy", true);
152 // Set up alternate_protocol for www.google.com:80.
153 base::DictionaryValue
* alternate_protocol
= new base::DictionaryValue
;
154 alternate_protocol
->SetInteger("port", 443);
155 alternate_protocol
->SetString("protocol_str", "npn-spdy/3");
156 server_pref_dict
->SetWithoutPathExpansion(
157 "alternate_protocol", alternate_protocol
);
159 // Set pipeline capability for www.google.com:80.
160 server_pref_dict
->SetInteger("pipeline_capability", net::PIPELINE_CAPABLE
);
162 // Set the server preference for www.google.com:80.
163 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
164 servers_dict
->SetWithoutPathExpansion(
165 "www.google.com:80", server_pref_dict
);
167 // Set the preference for mail.google.com server.
168 base::DictionaryValue
* server_pref_dict1
= new base::DictionaryValue
;
170 // Set supports_spdy for mail.google.com:80
171 server_pref_dict1
->SetBoolean("supports_spdy", true);
173 // Set up alternate_protocol for mail.google.com:80
174 base::DictionaryValue
* alternate_protocol1
= new base::DictionaryValue
;
175 alternate_protocol1
->SetInteger("port", 444);
176 alternate_protocol1
->SetString("protocol_str", "npn-spdy/3.1");
178 server_pref_dict1
->SetWithoutPathExpansion(
179 "alternate_protocol", alternate_protocol1
);
181 // Set pipelining capability for mail.google.com:80
182 server_pref_dict1
->SetInteger("pipeline_capability", net::PIPELINE_INCAPABLE
);
184 // Set the server preference for mail.google.com:80.
185 servers_dict
->SetWithoutPathExpansion(
186 "mail.google.com:80", server_pref_dict1
);
188 base::DictionaryValue
* http_server_properties_dict
=
189 new base::DictionaryValue
;
190 HttpServerPropertiesManager::SetVersion(http_server_properties_dict
, -1);
191 http_server_properties_dict
->SetWithoutPathExpansion("servers", servers_dict
);
193 // Set the same value for kHttpServerProperties multiple times.
194 pref_service_
.SetManagedPref(prefs::kHttpServerProperties
,
195 http_server_properties_dict
);
196 base::DictionaryValue
* http_server_properties_dict2
=
197 http_server_properties_dict
->DeepCopy();
198 pref_service_
.SetManagedPref(prefs::kHttpServerProperties
,
199 http_server_properties_dict2
);
201 loop_
.RunUntilIdle();
202 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
204 // Verify SupportsSpdy.
205 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(
206 net::HostPortPair::FromString("www.google.com:80")));
207 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(
208 net::HostPortPair::FromString("mail.google.com:80")));
209 EXPECT_FALSE(http_server_props_manager_
->SupportsSpdy(
210 net::HostPortPair::FromString("foo.google.com:1337")));
212 // Verify AlternateProtocol.
213 ASSERT_TRUE(http_server_props_manager_
->HasAlternateProtocol(
214 net::HostPortPair::FromString("www.google.com:80")));
215 ASSERT_TRUE(http_server_props_manager_
->HasAlternateProtocol(
216 net::HostPortPair::FromString("mail.google.com:80")));
217 net::PortAlternateProtocolPair port_alternate_protocol
=
218 http_server_props_manager_
->GetAlternateProtocol(
219 net::HostPortPair::FromString("www.google.com:80"));
220 EXPECT_EQ(443, port_alternate_protocol
.port
);
221 EXPECT_EQ(net::NPN_SPDY_3
, port_alternate_protocol
.protocol
);
222 port_alternate_protocol
=
223 http_server_props_manager_
->GetAlternateProtocol(
224 net::HostPortPair::FromString("mail.google.com:80"));
225 EXPECT_EQ(444, port_alternate_protocol
.port
);
226 EXPECT_EQ(net::NPN_SPDY_3_1
, port_alternate_protocol
.protocol
);
228 // Verify pipeline capability.
229 EXPECT_EQ(net::PIPELINE_CAPABLE
,
230 http_server_props_manager_
->GetPipelineCapability(
231 net::HostPortPair::FromString("www.google.com:80")));
232 EXPECT_EQ(net::PIPELINE_INCAPABLE
,
233 http_server_props_manager_
->GetPipelineCapability(
234 net::HostPortPair::FromString("mail.google.com:80")));
237 TEST_F(HttpServerPropertiesManagerTest
, SupportsSpdy
) {
240 // Post an update task to the IO thread. SetSupportsSpdy calls
241 // ScheduleUpdatePrefsOnIO.
243 // Add mail.google.com:443 as a supporting spdy server.
244 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
245 EXPECT_FALSE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
246 http_server_props_manager_
->SetSupportsSpdy(spdy_server_mail
, true);
249 loop_
.RunUntilIdle();
251 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
252 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
255 TEST_F(HttpServerPropertiesManagerTest
, SetSpdySetting
) {
258 // Add SpdySetting for mail.google.com:443.
259 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
260 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
261 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
262 const uint32 value1
= 31337;
263 http_server_props_manager_
->SetSpdySetting(
264 spdy_server_mail
, id1
, flags1
, value1
);
267 loop_
.RunUntilIdle();
269 const net::SettingsMap
& settings_map1_ret
=
270 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
271 ASSERT_EQ(1U, settings_map1_ret
.size());
272 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
273 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
274 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
275 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
276 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
278 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
281 TEST_F(HttpServerPropertiesManagerTest
, ClearSpdySetting
) {
282 ExpectPrefsUpdateRepeatedly();
284 // Add SpdySetting for mail.google.com:443.
285 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
286 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
287 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
288 const uint32 value1
= 31337;
289 http_server_props_manager_
->SetSpdySetting(
290 spdy_server_mail
, id1
, flags1
, value1
);
293 loop_
.RunUntilIdle();
295 const net::SettingsMap
& settings_map1_ret
=
296 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
297 ASSERT_EQ(1U, settings_map1_ret
.size());
298 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
299 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
300 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
301 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
302 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
304 // Clear SpdySetting for mail.google.com:443.
305 http_server_props_manager_
->ClearSpdySettings(spdy_server_mail
);
308 loop_
.RunUntilIdle();
310 // Verify that there are no entries in the settings map for
311 // mail.google.com:443.
312 const net::SettingsMap
& settings_map2_ret
=
313 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
314 ASSERT_EQ(0U, settings_map2_ret
.size());
316 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
319 TEST_F(HttpServerPropertiesManagerTest
, ClearAllSpdySetting
) {
320 ExpectPrefsUpdateRepeatedly();
322 // Add SpdySetting for mail.google.com:443.
323 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
324 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
325 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
326 const uint32 value1
= 31337;
327 http_server_props_manager_
->SetSpdySetting(
328 spdy_server_mail
, id1
, flags1
, value1
);
331 loop_
.RunUntilIdle();
333 const net::SettingsMap
& settings_map1_ret
=
334 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
335 ASSERT_EQ(1U, settings_map1_ret
.size());
336 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
337 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
338 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
339 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
340 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
342 // Clear All SpdySettings.
343 http_server_props_manager_
->ClearAllSpdySettings();
346 loop_
.RunUntilIdle();
348 // Verify that there are no entries in the settings map.
349 const net::SpdySettingsMap
& spdy_settings_map2_ret
=
350 http_server_props_manager_
->spdy_settings_map();
351 ASSERT_EQ(0U, spdy_settings_map2_ret
.size());
353 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
356 TEST_F(HttpServerPropertiesManagerTest
, HasAlternateProtocol
) {
359 net::HostPortPair
spdy_server_mail("mail.google.com", 80);
361 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
362 http_server_props_manager_
->SetAlternateProtocol(
363 spdy_server_mail
, 443, net::NPN_SPDY_3
);
366 loop_
.RunUntilIdle();
367 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
370 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
371 net::PortAlternateProtocolPair port_alternate_protocol
=
372 http_server_props_manager_
->GetAlternateProtocol(spdy_server_mail
);
373 EXPECT_EQ(443, port_alternate_protocol
.port
);
374 EXPECT_EQ(net::NPN_SPDY_3
, port_alternate_protocol
.protocol
);
377 TEST_F(HttpServerPropertiesManagerTest
, PipelineCapability
) {
380 net::HostPortPair
known_pipeliner("pipeline.com", 8080);
381 net::HostPortPair
bad_pipeliner("wordpress.com", 80);
382 EXPECT_EQ(net::PIPELINE_UNKNOWN
,
383 http_server_props_manager_
->GetPipelineCapability(known_pipeliner
));
384 EXPECT_EQ(net::PIPELINE_UNKNOWN
,
385 http_server_props_manager_
->GetPipelineCapability(bad_pipeliner
));
387 // Post an update task to the IO thread. SetPipelineCapability calls
388 // ScheduleUpdatePrefsOnIO.
389 http_server_props_manager_
->SetPipelineCapability(known_pipeliner
,
390 net::PIPELINE_CAPABLE
);
391 http_server_props_manager_
->SetPipelineCapability(bad_pipeliner
,
392 net::PIPELINE_INCAPABLE
);
395 loop_
.RunUntilIdle();
397 EXPECT_EQ(net::PIPELINE_CAPABLE
,
398 http_server_props_manager_
->GetPipelineCapability(known_pipeliner
));
399 EXPECT_EQ(net::PIPELINE_INCAPABLE
,
400 http_server_props_manager_
->GetPipelineCapability(bad_pipeliner
));
401 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
404 TEST_F(HttpServerPropertiesManagerTest
, Clear
) {
407 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
408 http_server_props_manager_
->SetSupportsSpdy(spdy_server_mail
, true);
409 http_server_props_manager_
->SetAlternateProtocol(
410 spdy_server_mail
, 443, net::NPN_SPDY_3
);
412 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
413 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
414 const uint32 value1
= 31337;
415 http_server_props_manager_
->SetSpdySetting(
416 spdy_server_mail
, id1
, flags1
, value1
);
418 net::HostPortPair
known_pipeliner("pipeline.com", 8080);
419 http_server_props_manager_
->SetPipelineCapability(known_pipeliner
,
420 net::PIPELINE_CAPABLE
);
423 loop_
.RunUntilIdle();
425 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
427 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
429 // Check SPDY settings values.
430 const net::SettingsMap
& settings_map1_ret
=
431 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
432 ASSERT_EQ(1U, settings_map1_ret
.size());
433 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
434 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
435 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
436 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
437 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
439 EXPECT_EQ(net::PIPELINE_CAPABLE
,
440 http_server_props_manager_
->GetPipelineCapability(known_pipeliner
));
442 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
446 // Clear http server data, time out if we do not get a completion callback.
447 http_server_props_manager_
->Clear(base::MessageLoop::QuitClosure());
450 EXPECT_FALSE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
452 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
454 const net::SettingsMap
& settings_map2_ret
=
455 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
456 EXPECT_EQ(0U, settings_map2_ret
.size());
458 EXPECT_EQ(net::PIPELINE_UNKNOWN
,
459 http_server_props_manager_
->GetPipelineCapability(known_pipeliner
));
461 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
464 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdateCache0
) {
465 // Post an update task to the UI thread.
466 http_server_props_manager_
->ScheduleUpdateCacheOnUI();
467 // Shutdown comes before the task is executed.
468 http_server_props_manager_
->ShutdownOnUIThread();
469 http_server_props_manager_
.reset();
470 // Run the task after shutdown and deletion.
471 loop_
.RunUntilIdle();
474 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdateCache1
) {
475 // Post an update task.
476 http_server_props_manager_
->ScheduleUpdateCacheOnUI();
477 // Shutdown comes before the task is executed.
478 http_server_props_manager_
->ShutdownOnUIThread();
479 // Run the task after shutdown, but before deletion.
480 loop_
.RunUntilIdle();
481 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
482 http_server_props_manager_
.reset();
483 loop_
.RunUntilIdle();
486 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdateCache2
) {
487 http_server_props_manager_
->UpdateCacheFromPrefsOnUIConcrete();
488 // Shutdown comes before the task is executed.
489 http_server_props_manager_
->ShutdownOnUIThread();
490 // Run the task after shutdown, but before deletion.
491 loop_
.RunUntilIdle();
492 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
493 http_server_props_manager_
.reset();
494 loop_
.RunUntilIdle();
498 // Tests for shutdown when updating prefs.
500 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdatePrefs0
) {
501 // Post an update task to the IO thread.
502 http_server_props_manager_
->ScheduleUpdatePrefsOnIO();
503 // Shutdown comes before the task is executed.
504 http_server_props_manager_
->ShutdownOnUIThread();
505 http_server_props_manager_
.reset();
506 // Run the task after shutdown and deletion.
507 loop_
.RunUntilIdle();
510 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdatePrefs1
) {
512 // Post an update task.
513 http_server_props_manager_
->ScheduleUpdatePrefsOnIO();
514 // Shutdown comes before the task is executed.
515 http_server_props_manager_
->ShutdownOnUIThread();
516 // Run the task after shutdown, but before deletion.
517 loop_
.RunUntilIdle();
518 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
519 http_server_props_manager_
.reset();
520 loop_
.RunUntilIdle();
523 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdatePrefs2
) {
524 // This posts a task to the UI thread.
525 http_server_props_manager_
->UpdatePrefsFromCacheOnIOConcrete(base::Closure());
526 // Shutdown comes before the task is executed.
527 http_server_props_manager_
->ShutdownOnUIThread();
528 // Run the task after shutdown, but before deletion.
529 loop_
.RunUntilIdle();
530 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
531 http_server_props_manager_
.reset();
532 loop_
.RunUntilIdle();
537 } // namespace chrome_browser_net