1 // Copyright 2014 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 "net/http/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/run_loop.h"
12 #include "base/test/test_simple_task_runner.h"
13 #include "base/values.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::Invoke
;
24 using ::testing::Mock
;
25 using ::testing::StrictMock
;
27 const char kTestHttpServerProperties
[] = "TestHttpServerProperties";
29 class TestingHttpServerPropertiesManager
: public HttpServerPropertiesManager
{
31 TestingHttpServerPropertiesManager(
32 PrefService
* pref_service
,
33 const char* pref_path
,
34 scoped_refptr
<base::SingleThreadTaskRunner
> io_task_runner
)
35 : HttpServerPropertiesManager(pref_service
, pref_path
, io_task_runner
) {
36 InitializeOnNetworkThread();
39 virtual ~TestingHttpServerPropertiesManager() {}
41 // Make these methods public for testing.
42 using HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread
;
43 using HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread
;
45 // Post tasks without a delay during tests.
46 virtual void StartPrefsUpdateTimerOnNetworkThread(
47 base::TimeDelta delay
) OVERRIDE
{
48 HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
52 void UpdateCacheFromPrefsOnUIConcrete() {
53 HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread();
56 // Post tasks without a delay during tests.
57 virtual void StartCacheUpdateTimerOnPrefThread(
58 base::TimeDelta delay
) OVERRIDE
{
59 HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
63 void UpdatePrefsFromCacheOnNetworkThreadConcrete(
64 const base::Closure
& callback
) {
65 HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(callback
);
68 MOCK_METHOD0(UpdateCacheFromPrefsOnPrefThread
, void());
69 MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkThread
, void(const base::Closure
&));
70 MOCK_METHOD5(UpdateCacheFromPrefsOnNetworkThread
,
71 void(std::vector
<std::string
>* spdy_servers
,
72 net::SpdySettingsMap
* spdy_settings_map
,
73 net::AlternateProtocolMap
* alternate_protocol_map
,
74 net::AlternateProtocolExperiment experiment
,
75 bool detected_corrupted_prefs
));
76 MOCK_METHOD3(UpdatePrefsOnPref
,
77 void(base::ListValue
* spdy_server_list
,
78 net::SpdySettingsMap
* spdy_settings_map
,
79 net::AlternateProtocolMap
* alternate_protocol_map
));
82 DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager
);
85 class HttpServerPropertiesManagerTest
: public testing::Test
{
87 HttpServerPropertiesManagerTest() {}
89 virtual void SetUp() OVERRIDE
{
90 pref_service_
.registry()->RegisterDictionaryPref(kTestHttpServerProperties
);
91 http_server_props_manager_
.reset(
92 new StrictMock
<TestingHttpServerPropertiesManager
>(
94 kTestHttpServerProperties
,
95 base::MessageLoop::current()->message_loop_proxy()));
97 base::RunLoop().RunUntilIdle();
100 virtual void TearDown() OVERRIDE
{
101 if (http_server_props_manager_
.get())
102 http_server_props_manager_
->ShutdownOnPrefThread();
103 base::RunLoop().RunUntilIdle();
104 http_server_props_manager_
.reset();
107 void ExpectCacheUpdate() {
108 EXPECT_CALL(*http_server_props_manager_
, UpdateCacheFromPrefsOnPrefThread())
109 .WillOnce(Invoke(http_server_props_manager_
.get(),
110 &TestingHttpServerPropertiesManager::
111 UpdateCacheFromPrefsOnUIConcrete
));
114 void ExpectPrefsUpdate() {
115 EXPECT_CALL(*http_server_props_manager_
,
116 UpdatePrefsFromCacheOnNetworkThread(_
))
117 .WillOnce(Invoke(http_server_props_manager_
.get(),
118 &TestingHttpServerPropertiesManager::
119 UpdatePrefsFromCacheOnNetworkThreadConcrete
));
122 void ExpectPrefsUpdateRepeatedly() {
123 EXPECT_CALL(*http_server_props_manager_
,
124 UpdatePrefsFromCacheOnNetworkThread(_
))
126 Invoke(http_server_props_manager_
.get(),
127 &TestingHttpServerPropertiesManager::
128 UpdatePrefsFromCacheOnNetworkThreadConcrete
));
131 //base::RunLoop loop_;
132 TestingPrefServiceSimple pref_service_
;
133 scoped_ptr
<TestingHttpServerPropertiesManager
> http_server_props_manager_
;
136 DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest
);
139 TEST_F(HttpServerPropertiesManagerTest
,
140 SingleUpdateForTwoSpdyServerPrefChanges
) {
143 // Set up the prefs for www.google.com:80 and mail.google.com:80 and then set
144 // it twice. Only expect a single cache update.
146 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
148 // Set supports_spdy for www.google.com:80.
149 server_pref_dict
->SetBoolean("supports_spdy", true);
151 // Set up alternate_protocol for www.google.com:80.
152 base::DictionaryValue
* alternate_protocol
= new base::DictionaryValue
;
153 alternate_protocol
->SetInteger("port", 443);
154 alternate_protocol
->SetString("protocol_str", "npn-spdy/3");
155 server_pref_dict
->SetWithoutPathExpansion("alternate_protocol",
158 // Set the server preference for www.google.com:80.
159 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
160 servers_dict
->SetWithoutPathExpansion("www.google.com:80", server_pref_dict
);
162 // Set the preference for mail.google.com server.
163 base::DictionaryValue
* server_pref_dict1
= new base::DictionaryValue
;
165 // Set supports_spdy for mail.google.com:80
166 server_pref_dict1
->SetBoolean("supports_spdy", true);
168 // Set up alternate_protocol for mail.google.com:80
169 base::DictionaryValue
* alternate_protocol1
= new base::DictionaryValue
;
170 alternate_protocol1
->SetInteger("port", 444);
171 alternate_protocol1
->SetString("protocol_str", "npn-spdy/3.1");
173 server_pref_dict1
->SetWithoutPathExpansion("alternate_protocol",
174 alternate_protocol1
);
176 // Set the server preference for mail.google.com:80.
177 servers_dict
->SetWithoutPathExpansion("mail.google.com:80",
180 base::DictionaryValue
* http_server_properties_dict
=
181 new base::DictionaryValue
;
182 HttpServerPropertiesManager::SetVersion(http_server_properties_dict
, -1);
183 http_server_properties_dict
->SetWithoutPathExpansion("servers", servers_dict
);
185 // Set the same value for kHttpServerProperties multiple times.
186 pref_service_
.SetManagedPref(kTestHttpServerProperties
,
187 http_server_properties_dict
);
188 base::DictionaryValue
* http_server_properties_dict2
=
189 http_server_properties_dict
->DeepCopy();
190 pref_service_
.SetManagedPref(kTestHttpServerProperties
,
191 http_server_properties_dict2
);
193 base::RunLoop().RunUntilIdle();
194 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
196 // Verify SupportsSpdy.
197 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(
198 net::HostPortPair::FromString("www.google.com:80")));
199 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(
200 net::HostPortPair::FromString("mail.google.com:80")));
201 EXPECT_FALSE(http_server_props_manager_
->SupportsSpdy(
202 net::HostPortPair::FromString("foo.google.com:1337")));
204 // Verify AlternateProtocol.
205 ASSERT_TRUE(http_server_props_manager_
->HasAlternateProtocol(
206 net::HostPortPair::FromString("www.google.com:80")));
207 ASSERT_TRUE(http_server_props_manager_
->HasAlternateProtocol(
208 net::HostPortPair::FromString("mail.google.com:80")));
209 net::AlternateProtocolInfo port_alternate_protocol
=
210 http_server_props_manager_
->GetAlternateProtocol(
211 net::HostPortPair::FromString("www.google.com:80"));
212 EXPECT_EQ(443, port_alternate_protocol
.port
);
213 EXPECT_EQ(net::NPN_SPDY_3
, port_alternate_protocol
.protocol
);
214 port_alternate_protocol
= http_server_props_manager_
->GetAlternateProtocol(
215 net::HostPortPair::FromString("mail.google.com:80"));
216 EXPECT_EQ(444, port_alternate_protocol
.port
);
217 EXPECT_EQ(net::NPN_SPDY_3_1
, port_alternate_protocol
.protocol
);
220 TEST_F(HttpServerPropertiesManagerTest
, SupportsSpdy
) {
223 // Post an update task to the network thread. SetSupportsSpdy calls
224 // ScheduleUpdatePrefsOnNetworkThread.
226 // Add mail.google.com:443 as a supporting spdy server.
227 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
228 EXPECT_FALSE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
229 http_server_props_manager_
->SetSupportsSpdy(spdy_server_mail
, true);
232 base::RunLoop().RunUntilIdle();
234 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
235 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
238 TEST_F(HttpServerPropertiesManagerTest
, SetSpdySetting
) {
241 // Add SpdySetting for mail.google.com:443.
242 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
243 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
244 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
245 const uint32 value1
= 31337;
246 http_server_props_manager_
->SetSpdySetting(
247 spdy_server_mail
, id1
, flags1
, value1
);
250 base::RunLoop().RunUntilIdle();
252 const net::SettingsMap
& settings_map1_ret
=
253 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
254 ASSERT_EQ(1U, settings_map1_ret
.size());
255 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
256 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
257 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
258 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
259 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
261 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
264 TEST_F(HttpServerPropertiesManagerTest
, ClearSpdySetting
) {
265 ExpectPrefsUpdateRepeatedly();
267 // Add SpdySetting for mail.google.com:443.
268 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
269 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
270 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
271 const uint32 value1
= 31337;
272 http_server_props_manager_
->SetSpdySetting(
273 spdy_server_mail
, id1
, flags1
, value1
);
276 base::RunLoop().RunUntilIdle();
278 const net::SettingsMap
& settings_map1_ret
=
279 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
280 ASSERT_EQ(1U, settings_map1_ret
.size());
281 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
282 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
283 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
284 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
285 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
287 // Clear SpdySetting for mail.google.com:443.
288 http_server_props_manager_
->ClearSpdySettings(spdy_server_mail
);
291 base::RunLoop().RunUntilIdle();
293 // Verify that there are no entries in the settings map for
294 // mail.google.com:443.
295 const net::SettingsMap
& settings_map2_ret
=
296 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
297 ASSERT_EQ(0U, settings_map2_ret
.size());
299 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
302 TEST_F(HttpServerPropertiesManagerTest
, ClearAllSpdySetting
) {
303 ExpectPrefsUpdateRepeatedly();
305 // Add SpdySetting for mail.google.com:443.
306 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
307 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
308 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
309 const uint32 value1
= 31337;
310 http_server_props_manager_
->SetSpdySetting(
311 spdy_server_mail
, id1
, flags1
, value1
);
314 base::RunLoop().RunUntilIdle();
316 const net::SettingsMap
& settings_map1_ret
=
317 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
318 ASSERT_EQ(1U, settings_map1_ret
.size());
319 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
320 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
321 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
322 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
323 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
325 // Clear All SpdySettings.
326 http_server_props_manager_
->ClearAllSpdySettings();
329 base::RunLoop().RunUntilIdle();
331 // Verify that there are no entries in the settings map.
332 const net::SpdySettingsMap
& spdy_settings_map2_ret
=
333 http_server_props_manager_
->spdy_settings_map();
334 ASSERT_EQ(0U, spdy_settings_map2_ret
.size());
336 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
339 TEST_F(HttpServerPropertiesManagerTest
, HasAlternateProtocol
) {
342 net::HostPortPair
spdy_server_mail("mail.google.com", 80);
344 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
345 http_server_props_manager_
->SetAlternateProtocol(
346 spdy_server_mail
, 443, net::NPN_SPDY_3
, 1);
349 base::RunLoop().RunUntilIdle();
350 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
353 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
354 net::AlternateProtocolInfo port_alternate_protocol
=
355 http_server_props_manager_
->GetAlternateProtocol(spdy_server_mail
);
356 EXPECT_EQ(443, port_alternate_protocol
.port
);
357 EXPECT_EQ(net::NPN_SPDY_3
, port_alternate_protocol
.protocol
);
360 TEST_F(HttpServerPropertiesManagerTest
, Clear
) {
363 net::HostPortPair
spdy_server_mail("mail.google.com", 443);
364 http_server_props_manager_
->SetSupportsSpdy(spdy_server_mail
, true);
365 http_server_props_manager_
->SetAlternateProtocol(
366 spdy_server_mail
, 443, net::NPN_SPDY_3
, 1);
368 const net::SpdySettingsIds id1
= net::SETTINGS_UPLOAD_BANDWIDTH
;
369 const net::SpdySettingsFlags flags1
= net::SETTINGS_FLAG_PLEASE_PERSIST
;
370 const uint32 value1
= 31337;
371 http_server_props_manager_
->SetSpdySetting(
372 spdy_server_mail
, id1
, flags1
, value1
);
375 base::RunLoop().RunUntilIdle();
377 EXPECT_TRUE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
379 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
381 // Check SPDY settings values.
382 const net::SettingsMap
& settings_map1_ret
=
383 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
384 ASSERT_EQ(1U, settings_map1_ret
.size());
385 net::SettingsMap::const_iterator it1_ret
= settings_map1_ret
.find(id1
);
386 EXPECT_TRUE(it1_ret
!= settings_map1_ret
.end());
387 net::SettingsFlagsAndValue flags_and_value1_ret
= it1_ret
->second
;
388 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED
, flags_and_value1_ret
.first
);
389 EXPECT_EQ(value1
, flags_and_value1_ret
.second
);
391 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
395 // Clear http server data, time out if we do not get a completion callback.
396 http_server_props_manager_
->Clear(base::MessageLoop::QuitClosure());
397 base::RunLoop().Run();
399 EXPECT_FALSE(http_server_props_manager_
->SupportsSpdy(spdy_server_mail
));
401 http_server_props_manager_
->HasAlternateProtocol(spdy_server_mail
));
403 const net::SettingsMap
& settings_map2_ret
=
404 http_server_props_manager_
->GetSpdySettings(spdy_server_mail
);
405 EXPECT_EQ(0U, settings_map2_ret
.size());
407 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
410 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdateCache0
) {
411 // Post an update task to the UI thread.
412 http_server_props_manager_
->ScheduleUpdateCacheOnPrefThread();
413 // Shutdown comes before the task is executed.
414 http_server_props_manager_
->ShutdownOnPrefThread();
415 http_server_props_manager_
.reset();
416 // Run the task after shutdown and deletion.
417 base::RunLoop().RunUntilIdle();
420 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdateCache1
) {
421 // Post an update task.
422 http_server_props_manager_
->ScheduleUpdateCacheOnPrefThread();
423 // Shutdown comes before the task is executed.
424 http_server_props_manager_
->ShutdownOnPrefThread();
425 // Run the task after shutdown, but before deletion.
426 base::RunLoop().RunUntilIdle();
427 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
428 http_server_props_manager_
.reset();
429 base::RunLoop().RunUntilIdle();
432 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdateCache2
) {
433 http_server_props_manager_
->UpdateCacheFromPrefsOnUIConcrete();
434 // Shutdown comes before the task is executed.
435 http_server_props_manager_
->ShutdownOnPrefThread();
436 // Run the task after shutdown, but before deletion.
437 base::RunLoop().RunUntilIdle();
438 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
439 http_server_props_manager_
.reset();
440 base::RunLoop().RunUntilIdle();
444 // Tests for shutdown when updating prefs.
446 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdatePrefs0
) {
447 // Post an update task to the IO thread.
448 http_server_props_manager_
->ScheduleUpdatePrefsOnNetworkThread();
449 // Shutdown comes before the task is executed.
450 http_server_props_manager_
->ShutdownOnPrefThread();
451 http_server_props_manager_
.reset();
452 // Run the task after shutdown and deletion.
453 base::RunLoop().RunUntilIdle();
456 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdatePrefs1
) {
458 // Post an update task.
459 http_server_props_manager_
->ScheduleUpdatePrefsOnNetworkThread();
460 // Shutdown comes before the task is executed.
461 http_server_props_manager_
->ShutdownOnPrefThread();
462 // Run the task after shutdown, but before deletion.
463 base::RunLoop().RunUntilIdle();
464 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
465 http_server_props_manager_
.reset();
466 base::RunLoop().RunUntilIdle();
469 TEST_F(HttpServerPropertiesManagerTest
, ShutdownWithPendingUpdatePrefs2
) {
470 // This posts a task to the UI thread.
471 http_server_props_manager_
->UpdatePrefsFromCacheOnNetworkThreadConcrete(
473 // Shutdown comes before the task is executed.
474 http_server_props_manager_
->ShutdownOnPrefThread();
475 // Run the task after shutdown, but before deletion.
476 base::RunLoop().RunUntilIdle();
477 Mock::VerifyAndClearExpectations(http_server_props_manager_
.get());
478 http_server_props_manager_
.reset();
479 base::RunLoop().RunUntilIdle();