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::SupportsQuicMap* supports_quic_map,
75 bool detected_corrupted_prefs));
76 MOCK_METHOD4(UpdatePrefsOnPref,
77 void(base::ListValue* spdy_server_list,
78 net::SpdySettingsMap* spdy_settings_map,
79 net::AlternateProtocolMap* alternate_protocol_map,
80 net::SupportsQuicMap* supports_quic_map));
83 DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager);
86 class HttpServerPropertiesManagerTest : public testing::Test {
88 HttpServerPropertiesManagerTest() {}
90 void SetUp() override {
91 pref_service_.registry()->RegisterDictionaryPref(kTestHttpServerProperties);
92 http_server_props_manager_.reset(
93 new StrictMock<TestingHttpServerPropertiesManager>(
95 kTestHttpServerProperties,
96 base::MessageLoop::current()->message_loop_proxy()));
98 base::RunLoop().RunUntilIdle();
101 void TearDown() override {
102 if (http_server_props_manager_.get())
103 http_server_props_manager_->ShutdownOnPrefThread();
104 base::RunLoop().RunUntilIdle();
105 http_server_props_manager_.reset();
108 void ExpectCacheUpdate() {
109 EXPECT_CALL(*http_server_props_manager_, UpdateCacheFromPrefsOnPrefThread())
110 .WillOnce(Invoke(http_server_props_manager_.get(),
111 &TestingHttpServerPropertiesManager::
112 UpdateCacheFromPrefsOnUIConcrete));
115 void ExpectPrefsUpdate() {
116 EXPECT_CALL(*http_server_props_manager_,
117 UpdatePrefsFromCacheOnNetworkThread(_))
118 .WillOnce(Invoke(http_server_props_manager_.get(),
119 &TestingHttpServerPropertiesManager::
120 UpdatePrefsFromCacheOnNetworkThreadConcrete));
123 void ExpectPrefsUpdateRepeatedly() {
124 EXPECT_CALL(*http_server_props_manager_,
125 UpdatePrefsFromCacheOnNetworkThread(_))
127 Invoke(http_server_props_manager_.get(),
128 &TestingHttpServerPropertiesManager::
129 UpdatePrefsFromCacheOnNetworkThreadConcrete));
132 //base::RunLoop loop_;
133 TestingPrefServiceSimple pref_service_;
134 scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
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("alternate_protocol",
159 // Set up SupportsQuic for www.google.com:80.
160 base::DictionaryValue* supports_quic = new base::DictionaryValue;
161 supports_quic->SetBoolean("used_quic", true);
162 supports_quic->SetString("address", "foo");
163 server_pref_dict->SetWithoutPathExpansion("supports_quic", supports_quic);
165 // Set the server preference for www.google.com:80.
166 base::DictionaryValue* servers_dict = new base::DictionaryValue;
167 servers_dict->SetWithoutPathExpansion("www.google.com:80", server_pref_dict);
169 // Set the preference for mail.google.com server.
170 base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue;
172 // Set supports_spdy for mail.google.com:80
173 server_pref_dict1->SetBoolean("supports_spdy", true);
175 // Set up alternate_protocol for mail.google.com:80
176 base::DictionaryValue* alternate_protocol1 = new base::DictionaryValue;
177 alternate_protocol1->SetInteger("port", 444);
178 alternate_protocol1->SetString("protocol_str", "npn-spdy/3.1");
180 server_pref_dict1->SetWithoutPathExpansion("alternate_protocol",
181 alternate_protocol1);
183 // Set up SupportsQuic for mail.google.com:80
184 base::DictionaryValue* supports_quic1 = new base::DictionaryValue;
185 supports_quic1->SetBoolean("used_quic", false);
186 supports_quic1->SetString("address", "bar");
187 server_pref_dict1->SetWithoutPathExpansion("supports_quic", supports_quic1);
189 // Set the server preference for mail.google.com:80.
190 servers_dict->SetWithoutPathExpansion("mail.google.com:80",
193 base::DictionaryValue* http_server_properties_dict =
194 new base::DictionaryValue;
195 HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
196 http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
198 // Set the same value for kHttpServerProperties multiple times.
199 pref_service_.SetManagedPref(kTestHttpServerProperties,
200 http_server_properties_dict);
201 base::DictionaryValue* http_server_properties_dict2 =
202 http_server_properties_dict->DeepCopy();
203 pref_service_.SetManagedPref(kTestHttpServerProperties,
204 http_server_properties_dict2);
206 base::RunLoop().RunUntilIdle();
207 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
209 // Verify SupportsSpdy.
210 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
211 net::HostPortPair::FromString("www.google.com:80")));
212 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
213 net::HostPortPair::FromString("mail.google.com:80")));
214 EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(
215 net::HostPortPair::FromString("foo.google.com:1337")));
217 // Verify AlternateProtocol.
218 ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
219 net::HostPortPair::FromString("www.google.com:80")));
220 ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
221 net::HostPortPair::FromString("mail.google.com:80")));
222 net::AlternateProtocolInfo port_alternate_protocol =
223 http_server_props_manager_->GetAlternateProtocol(
224 net::HostPortPair::FromString("www.google.com:80"));
225 EXPECT_EQ(443, port_alternate_protocol.port);
226 EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
227 port_alternate_protocol = http_server_props_manager_->GetAlternateProtocol(
228 net::HostPortPair::FromString("mail.google.com:80"));
229 EXPECT_EQ(444, port_alternate_protocol.port);
230 EXPECT_EQ(net::NPN_SPDY_3_1, port_alternate_protocol.protocol);
232 // Verify SupportsQuic.
233 net::SupportsQuic supports_quic2 =
234 http_server_props_manager_->GetSupportsQuic(
235 net::HostPortPair::FromString("www.google.com:80"));
236 EXPECT_TRUE(supports_quic2.used_quic);
237 EXPECT_EQ("foo", supports_quic2.address);
238 supports_quic2 = http_server_props_manager_->GetSupportsQuic(
239 net::HostPortPair::FromString("mail.google.com:80"));
240 EXPECT_FALSE(supports_quic2.used_quic);
241 EXPECT_EQ("bar", supports_quic2.address);
244 TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
247 // Post an update task to the network thread. SetSupportsSpdy calls
248 // ScheduleUpdatePrefsOnNetworkThread.
250 // Add mail.google.com:443 as a supporting spdy server.
251 net::HostPortPair spdy_server_mail("mail.google.com", 443);
252 EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
253 http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
256 base::RunLoop().RunUntilIdle();
258 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
259 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
262 TEST_F(HttpServerPropertiesManagerTest, SetSpdySetting) {
265 // Add SpdySetting for mail.google.com:443.
266 net::HostPortPair spdy_server_mail("mail.google.com", 443);
267 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
268 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
269 const uint32 value1 = 31337;
270 http_server_props_manager_->SetSpdySetting(
271 spdy_server_mail, id1, flags1, value1);
274 base::RunLoop().RunUntilIdle();
276 const net::SettingsMap& settings_map1_ret =
277 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
278 ASSERT_EQ(1U, settings_map1_ret.size());
279 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
280 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
281 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
282 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
283 EXPECT_EQ(value1, flags_and_value1_ret.second);
285 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
288 TEST_F(HttpServerPropertiesManagerTest, ClearSpdySetting) {
289 ExpectPrefsUpdateRepeatedly();
291 // Add SpdySetting for mail.google.com:443.
292 net::HostPortPair spdy_server_mail("mail.google.com", 443);
293 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
294 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
295 const uint32 value1 = 31337;
296 http_server_props_manager_->SetSpdySetting(
297 spdy_server_mail, id1, flags1, value1);
300 base::RunLoop().RunUntilIdle();
302 const net::SettingsMap& settings_map1_ret =
303 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
304 ASSERT_EQ(1U, settings_map1_ret.size());
305 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
306 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
307 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
308 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
309 EXPECT_EQ(value1, flags_and_value1_ret.second);
311 // Clear SpdySetting for mail.google.com:443.
312 http_server_props_manager_->ClearSpdySettings(spdy_server_mail);
315 base::RunLoop().RunUntilIdle();
317 // Verify that there are no entries in the settings map for
318 // mail.google.com:443.
319 const net::SettingsMap& settings_map2_ret =
320 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
321 ASSERT_EQ(0U, settings_map2_ret.size());
323 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
326 TEST_F(HttpServerPropertiesManagerTest, ClearAllSpdySetting) {
327 ExpectPrefsUpdateRepeatedly();
329 // Add SpdySetting for mail.google.com:443.
330 net::HostPortPair spdy_server_mail("mail.google.com", 443);
331 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
332 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
333 const uint32 value1 = 31337;
334 http_server_props_manager_->SetSpdySetting(
335 spdy_server_mail, id1, flags1, value1);
338 base::RunLoop().RunUntilIdle();
340 const net::SettingsMap& settings_map1_ret =
341 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
342 ASSERT_EQ(1U, settings_map1_ret.size());
343 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
344 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
345 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
346 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
347 EXPECT_EQ(value1, flags_and_value1_ret.second);
349 // Clear All SpdySettings.
350 http_server_props_manager_->ClearAllSpdySettings();
353 base::RunLoop().RunUntilIdle();
355 // Verify that there are no entries in the settings map.
356 const net::SpdySettingsMap& spdy_settings_map2_ret =
357 http_server_props_manager_->spdy_settings_map();
358 ASSERT_EQ(0U, spdy_settings_map2_ret.size());
360 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
363 TEST_F(HttpServerPropertiesManagerTest, HasAlternateProtocol) {
366 net::HostPortPair spdy_server_mail("mail.google.com", 80);
368 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
369 http_server_props_manager_->SetAlternateProtocol(
370 spdy_server_mail, 443, net::NPN_SPDY_3, 1);
373 base::RunLoop().RunUntilIdle();
374 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
377 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
378 net::AlternateProtocolInfo port_alternate_protocol =
379 http_server_props_manager_->GetAlternateProtocol(spdy_server_mail);
380 EXPECT_EQ(443, port_alternate_protocol.port);
381 EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
384 TEST_F(HttpServerPropertiesManagerTest, SupportsQuic) {
387 net::HostPortPair quic_server_mail("mail.google.com", 80);
388 net::SupportsQuic supports_quic = http_server_props_manager_->GetSupportsQuic(
390 EXPECT_FALSE(supports_quic.used_quic);
391 EXPECT_EQ("", supports_quic.address);
392 http_server_props_manager_->SetSupportsQuic(quic_server_mail, true, "foo");
395 base::RunLoop().RunUntilIdle();
396 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
398 net::SupportsQuic supports_quic1 =
399 http_server_props_manager_->GetSupportsQuic(quic_server_mail);
400 EXPECT_TRUE(supports_quic1.used_quic);
401 EXPECT_EQ("foo", supports_quic1.address);
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, 1);
411 http_server_props_manager_->SetSupportsQuic(spdy_server_mail, true, "foo");
413 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
414 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
415 const uint32 value1 = 31337;
416 http_server_props_manager_->SetSpdySetting(
417 spdy_server_mail, id1, flags1, value1);
420 base::RunLoop().RunUntilIdle();
422 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
424 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
425 net::SupportsQuic supports_quic = http_server_props_manager_->GetSupportsQuic(
427 EXPECT_TRUE(supports_quic.used_quic);
428 EXPECT_EQ("foo", supports_quic.address);
430 // Check SPDY settings values.
431 const net::SettingsMap& settings_map1_ret =
432 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
433 ASSERT_EQ(1U, settings_map1_ret.size());
434 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
435 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
436 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
437 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
438 EXPECT_EQ(value1, flags_and_value1_ret.second);
440 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
444 // Clear http server data, time out if we do not get a completion callback.
445 http_server_props_manager_->Clear(base::MessageLoop::QuitClosure());
446 base::RunLoop().Run();
448 EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
450 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
451 net::SupportsQuic supports_quic1 =
452 http_server_props_manager_->GetSupportsQuic(spdy_server_mail);
453 EXPECT_FALSE(supports_quic1.used_quic);
454 EXPECT_EQ("", supports_quic1.address);
456 const net::SettingsMap& settings_map2_ret =
457 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
458 EXPECT_EQ(0U, settings_map2_ret.size());
460 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
463 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
464 // Post an update task to the UI thread.
465 http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
466 // Shutdown comes before the task is executed.
467 http_server_props_manager_->ShutdownOnPrefThread();
468 http_server_props_manager_.reset();
469 // Run the task after shutdown and deletion.
470 base::RunLoop().RunUntilIdle();
473 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) {
474 // Post an update task.
475 http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
476 // Shutdown comes before the task is executed.
477 http_server_props_manager_->ShutdownOnPrefThread();
478 // Run the task after shutdown, but before deletion.
479 base::RunLoop().RunUntilIdle();
480 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
481 http_server_props_manager_.reset();
482 base::RunLoop().RunUntilIdle();
485 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) {
486 http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete();
487 // Shutdown comes before the task is executed.
488 http_server_props_manager_->ShutdownOnPrefThread();
489 // Run the task after shutdown, but before deletion.
490 base::RunLoop().RunUntilIdle();
491 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
492 http_server_props_manager_.reset();
493 base::RunLoop().RunUntilIdle();
497 // Tests for shutdown when updating prefs.
499 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) {
500 // Post an update task to the IO thread.
501 http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThread();
502 // Shutdown comes before the task is executed.
503 http_server_props_manager_->ShutdownOnPrefThread();
504 http_server_props_manager_.reset();
505 // Run the task after shutdown and deletion.
506 base::RunLoop().RunUntilIdle();
509 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
511 // Post an update task.
512 http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThread();
513 // Shutdown comes before the task is executed.
514 http_server_props_manager_->ShutdownOnPrefThread();
515 // Run the task after shutdown, but before deletion.
516 base::RunLoop().RunUntilIdle();
517 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
518 http_server_props_manager_.reset();
519 base::RunLoop().RunUntilIdle();
522 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
523 // This posts a task to the UI thread.
524 http_server_props_manager_->UpdatePrefsFromCacheOnNetworkThreadConcrete(
526 // Shutdown comes before the task is executed.
527 http_server_props_manager_->ShutdownOnPrefThread();
528 // Run the task after shutdown, but before deletion.
529 base::RunLoop().RunUntilIdle();
530 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
531 http_server_props_manager_.reset();
532 base::RunLoop().RunUntilIdle();