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::AlternateProtocolExperiment experiment,
69 bool detected_corrupted_prefs));
70 MOCK_METHOD3(UpdatePrefsOnUI,
71 void(base::ListValue* spdy_server_list,
72 net::SpdySettingsMap* spdy_settings_map,
73 net::AlternateProtocolMap* alternate_protocol_map));
76 DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager);
79 class HttpServerPropertiesManagerTest : public testing::Test {
81 HttpServerPropertiesManagerTest()
82 : ui_thread_(BrowserThread::UI, &loop_),
83 io_thread_(BrowserThread::IO, &loop_) {
86 virtual void SetUp() OVERRIDE {
87 pref_service_.registry()->RegisterDictionaryPref(
88 prefs::kHttpServerProperties);
89 http_server_props_manager_.reset(
90 new StrictMock<TestingHttpServerPropertiesManager>(&pref_service_));
95 virtual void TearDown() OVERRIDE {
96 if (http_server_props_manager_.get())
97 http_server_props_manager_->ShutdownOnUIThread();
99 // Delete |http_server_props_manager_| while |io_thread_| is mapping IO to
101 http_server_props_manager_.reset();
104 void ExpectCacheUpdate() {
105 EXPECT_CALL(*http_server_props_manager_, UpdateCacheFromPrefsOnUI())
107 Invoke(http_server_props_manager_.get(),
108 &TestingHttpServerPropertiesManager::
109 UpdateCacheFromPrefsOnUIConcrete));
112 void ExpectPrefsUpdate() {
113 EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnIO(_))
115 Invoke(http_server_props_manager_.get(),
116 &TestingHttpServerPropertiesManager::
117 UpdatePrefsFromCacheOnIOConcrete));
120 void ExpectPrefsUpdateRepeatedly() {
121 EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnIO(_))
123 Invoke(http_server_props_manager_.get(),
124 &TestingHttpServerPropertiesManager::
125 UpdatePrefsFromCacheOnIOConcrete));
128 base::MessageLoop loop_;
129 TestingPrefServiceSimple pref_service_;
130 scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
133 content::TestBrowserThread ui_thread_;
134 content::TestBrowserThread io_thread_;
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(
156 "alternate_protocol", alternate_protocol);
158 // Set the server preference for www.google.com:80.
159 base::DictionaryValue* servers_dict = new base::DictionaryValue;
160 servers_dict->SetWithoutPathExpansion(
161 "www.google.com:80", server_pref_dict);
163 // Set the preference for mail.google.com server.
164 base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue;
166 // Set supports_spdy for mail.google.com:80
167 server_pref_dict1->SetBoolean("supports_spdy", true);
169 // Set up alternate_protocol for mail.google.com:80
170 base::DictionaryValue* alternate_protocol1 = new base::DictionaryValue;
171 alternate_protocol1->SetInteger("port", 444);
172 alternate_protocol1->SetString("protocol_str", "npn-spdy/3.1");
174 server_pref_dict1->SetWithoutPathExpansion(
175 "alternate_protocol", alternate_protocol1);
177 // Set the server preference for mail.google.com:80.
178 servers_dict->SetWithoutPathExpansion(
179 "mail.google.com:80", server_pref_dict1);
181 base::DictionaryValue* http_server_properties_dict =
182 new base::DictionaryValue;
183 HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
184 http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
186 // Set the same value for kHttpServerProperties multiple times.
187 pref_service_.SetManagedPref(prefs::kHttpServerProperties,
188 http_server_properties_dict);
189 base::DictionaryValue* http_server_properties_dict2 =
190 http_server_properties_dict->DeepCopy();
191 pref_service_.SetManagedPref(prefs::kHttpServerProperties,
192 http_server_properties_dict2);
194 loop_.RunUntilIdle();
195 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
197 // Verify SupportsSpdy.
198 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
199 net::HostPortPair::FromString("www.google.com:80")));
200 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
201 net::HostPortPair::FromString("mail.google.com:80")));
202 EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(
203 net::HostPortPair::FromString("foo.google.com:1337")));
205 // Verify AlternateProtocol.
206 ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
207 net::HostPortPair::FromString("www.google.com:80")));
208 ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
209 net::HostPortPair::FromString("mail.google.com:80")));
210 net::PortAlternateProtocolPair port_alternate_protocol =
211 http_server_props_manager_->GetAlternateProtocol(
212 net::HostPortPair::FromString("www.google.com:80"));
213 EXPECT_EQ(443, port_alternate_protocol.port);
214 EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
215 port_alternate_protocol =
216 http_server_props_manager_->GetAlternateProtocol(
217 net::HostPortPair::FromString("mail.google.com:80"));
218 EXPECT_EQ(444, port_alternate_protocol.port);
219 EXPECT_EQ(net::NPN_SPDY_3_1, port_alternate_protocol.protocol);
222 TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
225 // Post an update task to the IO thread. SetSupportsSpdy calls
226 // ScheduleUpdatePrefsOnIO.
228 // Add mail.google.com:443 as a supporting spdy server.
229 net::HostPortPair spdy_server_mail("mail.google.com", 443);
230 EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
231 http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
234 loop_.RunUntilIdle();
236 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
237 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
240 TEST_F(HttpServerPropertiesManagerTest, SetSpdySetting) {
243 // Add SpdySetting for mail.google.com:443.
244 net::HostPortPair spdy_server_mail("mail.google.com", 443);
245 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
246 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
247 const uint32 value1 = 31337;
248 http_server_props_manager_->SetSpdySetting(
249 spdy_server_mail, id1, flags1, value1);
252 loop_.RunUntilIdle();
254 const net::SettingsMap& settings_map1_ret =
255 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
256 ASSERT_EQ(1U, settings_map1_ret.size());
257 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
258 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
259 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
260 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
261 EXPECT_EQ(value1, flags_and_value1_ret.second);
263 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
266 TEST_F(HttpServerPropertiesManagerTest, ClearSpdySetting) {
267 ExpectPrefsUpdateRepeatedly();
269 // Add SpdySetting for mail.google.com:443.
270 net::HostPortPair spdy_server_mail("mail.google.com", 443);
271 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
272 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
273 const uint32 value1 = 31337;
274 http_server_props_manager_->SetSpdySetting(
275 spdy_server_mail, id1, flags1, value1);
278 loop_.RunUntilIdle();
280 const net::SettingsMap& settings_map1_ret =
281 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
282 ASSERT_EQ(1U, settings_map1_ret.size());
283 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
284 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
285 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
286 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
287 EXPECT_EQ(value1, flags_and_value1_ret.second);
289 // Clear SpdySetting for mail.google.com:443.
290 http_server_props_manager_->ClearSpdySettings(spdy_server_mail);
293 loop_.RunUntilIdle();
295 // Verify that there are no entries in the settings map for
296 // mail.google.com:443.
297 const net::SettingsMap& settings_map2_ret =
298 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
299 ASSERT_EQ(0U, settings_map2_ret.size());
301 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
304 TEST_F(HttpServerPropertiesManagerTest, ClearAllSpdySetting) {
305 ExpectPrefsUpdateRepeatedly();
307 // Add SpdySetting for mail.google.com:443.
308 net::HostPortPair spdy_server_mail("mail.google.com", 443);
309 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
310 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
311 const uint32 value1 = 31337;
312 http_server_props_manager_->SetSpdySetting(
313 spdy_server_mail, id1, flags1, value1);
316 loop_.RunUntilIdle();
318 const net::SettingsMap& settings_map1_ret =
319 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
320 ASSERT_EQ(1U, settings_map1_ret.size());
321 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
322 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
323 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
324 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
325 EXPECT_EQ(value1, flags_and_value1_ret.second);
327 // Clear All SpdySettings.
328 http_server_props_manager_->ClearAllSpdySettings();
331 loop_.RunUntilIdle();
333 // Verify that there are no entries in the settings map.
334 const net::SpdySettingsMap& spdy_settings_map2_ret =
335 http_server_props_manager_->spdy_settings_map();
336 ASSERT_EQ(0U, spdy_settings_map2_ret.size());
338 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
341 TEST_F(HttpServerPropertiesManagerTest, HasAlternateProtocol) {
344 net::HostPortPair spdy_server_mail("mail.google.com", 80);
346 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
347 http_server_props_manager_->SetAlternateProtocol(
348 spdy_server_mail, 443, net::NPN_SPDY_3);
351 loop_.RunUntilIdle();
352 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
355 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
356 net::PortAlternateProtocolPair port_alternate_protocol =
357 http_server_props_manager_->GetAlternateProtocol(spdy_server_mail);
358 EXPECT_EQ(443, port_alternate_protocol.port);
359 EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
362 TEST_F(HttpServerPropertiesManagerTest, Clear) {
365 net::HostPortPair spdy_server_mail("mail.google.com", 443);
366 http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
367 http_server_props_manager_->SetAlternateProtocol(
368 spdy_server_mail, 443, net::NPN_SPDY_3);
370 const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
371 const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
372 const uint32 value1 = 31337;
373 http_server_props_manager_->SetSpdySetting(
374 spdy_server_mail, id1, flags1, value1);
377 loop_.RunUntilIdle();
379 EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
381 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
383 // Check SPDY settings values.
384 const net::SettingsMap& settings_map1_ret =
385 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
386 ASSERT_EQ(1U, settings_map1_ret.size());
387 net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
388 EXPECT_TRUE(it1_ret != settings_map1_ret.end());
389 net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
390 EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
391 EXPECT_EQ(value1, flags_and_value1_ret.second);
393 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
397 // Clear http server data, time out if we do not get a completion callback.
398 http_server_props_manager_->Clear(base::MessageLoop::QuitClosure());
401 EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
403 http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
405 const net::SettingsMap& settings_map2_ret =
406 http_server_props_manager_->GetSpdySettings(spdy_server_mail);
407 EXPECT_EQ(0U, settings_map2_ret.size());
409 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
412 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
413 // Post an update task to the UI thread.
414 http_server_props_manager_->ScheduleUpdateCacheOnUI();
415 // Shutdown comes before the task is executed.
416 http_server_props_manager_->ShutdownOnUIThread();
417 http_server_props_manager_.reset();
418 // Run the task after shutdown and deletion.
419 loop_.RunUntilIdle();
422 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) {
423 // Post an update task.
424 http_server_props_manager_->ScheduleUpdateCacheOnUI();
425 // Shutdown comes before the task is executed.
426 http_server_props_manager_->ShutdownOnUIThread();
427 // Run the task after shutdown, but before deletion.
428 loop_.RunUntilIdle();
429 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
430 http_server_props_manager_.reset();
431 loop_.RunUntilIdle();
434 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) {
435 http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete();
436 // Shutdown comes before the task is executed.
437 http_server_props_manager_->ShutdownOnUIThread();
438 // Run the task after shutdown, but before deletion.
439 loop_.RunUntilIdle();
440 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
441 http_server_props_manager_.reset();
442 loop_.RunUntilIdle();
446 // Tests for shutdown when updating prefs.
448 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) {
449 // Post an update task to the IO thread.
450 http_server_props_manager_->ScheduleUpdatePrefsOnIO();
451 // Shutdown comes before the task is executed.
452 http_server_props_manager_->ShutdownOnUIThread();
453 http_server_props_manager_.reset();
454 // Run the task after shutdown and deletion.
455 loop_.RunUntilIdle();
458 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
460 // Post an update task.
461 http_server_props_manager_->ScheduleUpdatePrefsOnIO();
462 // Shutdown comes before the task is executed.
463 http_server_props_manager_->ShutdownOnUIThread();
464 // Run the task after shutdown, but before deletion.
465 loop_.RunUntilIdle();
466 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
467 http_server_props_manager_.reset();
468 loop_.RunUntilIdle();
471 TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
472 // This posts a task to the UI thread.
473 http_server_props_manager_->UpdatePrefsFromCacheOnIOConcrete(base::Closure());
474 // Shutdown comes before the task is executed.
475 http_server_props_manager_->ShutdownOnUIThread();
476 // Run the task after shutdown, but before deletion.
477 loop_.RunUntilIdle();
478 Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
479 http_server_props_manager_.reset();
480 loop_.RunUntilIdle();
485 } // namespace chrome_browser_net