// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/http/http_server_properties_manager.h" #include "base/basictypes.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/message_loop/message_loop.h" #include "base/prefs/pref_registry_simple.h" #include "base/prefs/testing_pref_service.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/test/test_simple_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/values.h" #include "net/base/ip_address_number.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace net { namespace { using base::StringPrintf; using ::testing::_; using ::testing::Invoke; using ::testing::Mock; using ::testing::StrictMock; const char kTestHttpServerProperties[] = "TestHttpServerProperties"; class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager { public: TestingHttpServerPropertiesManager( PrefService* pref_service, const char* pref_path, scoped_refptr io_task_runner) : HttpServerPropertiesManager(pref_service, pref_path, io_task_runner) { InitializeOnNetworkThread(); } ~TestingHttpServerPropertiesManager() override {} // Make these methods public for testing. using HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread; // Post tasks without a delay during tests. void StartPrefsUpdateTimerOnNetworkThread(base::TimeDelta delay) override { HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread( base::TimeDelta()); } void UpdateCacheFromPrefsOnUIConcrete() { HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread(); } // Post tasks without a delay during tests. void StartCacheUpdateTimerOnPrefThread(base::TimeDelta delay) override { HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread( base::TimeDelta()); } void UpdatePrefsFromCacheOnNetworkThreadConcrete( const base::Closure& callback) { HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(callback); } void ScheduleUpdatePrefsOnNetworkThreadConcrete(Location location) { HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(location); } void ScheduleUpdatePrefsOnNetworkThread() { // Picked a random Location as caller. HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread( DETECTED_CORRUPTED_PREFS); } MOCK_METHOD0(UpdateCacheFromPrefsOnPrefThread, void()); MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkThread, void(const base::Closure&)); MOCK_METHOD1(ScheduleUpdatePrefsOnNetworkThread, void(Location location)); MOCK_METHOD7(UpdateCacheFromPrefsOnNetworkThread, void(std::vector* spdy_servers, SpdySettingsMap* spdy_settings_map, AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, QuicServerInfoMap* quic_server_info_map, bool detected_corrupted_prefs)); MOCK_METHOD7(UpdatePrefsOnPrefThread, void(base::ListValue* spdy_server_list, SpdySettingsMap* spdy_settings_map, AlternativeServiceMap* alternative_service_map, IPAddressNumber* last_quic_address, ServerNetworkStatsMap* server_network_stats_map, QuicServerInfoMap* quic_server_info_map, const base::Closure& completion)); private: DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager); }; } // namespace class HttpServerPropertiesManagerTest : public testing::Test { protected: HttpServerPropertiesManagerTest() {} void SetUp() override { one_day_from_now_ = base::Time::Now() + base::TimeDelta::FromDays(1); pref_service_.registry()->RegisterDictionaryPref(kTestHttpServerProperties); http_server_props_manager_.reset( new StrictMock( &pref_service_, kTestHttpServerProperties, base::ThreadTaskRunnerHandle::Get())); ExpectCacheUpdate(); base::RunLoop().RunUntilIdle(); } void TearDown() override { if (http_server_props_manager_.get()) http_server_props_manager_->ShutdownOnPrefThread(); base::RunLoop().RunUntilIdle(); http_server_props_manager_.reset(); } void ExpectCacheUpdate() { EXPECT_CALL(*http_server_props_manager_, UpdateCacheFromPrefsOnPrefThread()) .WillOnce(Invoke(http_server_props_manager_.get(), &TestingHttpServerPropertiesManager:: UpdateCacheFromPrefsOnUIConcrete)); } void ExpectScheduleUpdatePrefsOnNetworkThread() { EXPECT_CALL(*http_server_props_manager_, ScheduleUpdatePrefsOnNetworkThread(_)) .WillOnce(Invoke(http_server_props_manager_.get(), &TestingHttpServerPropertiesManager:: ScheduleUpdatePrefsOnNetworkThreadConcrete)); } void ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly() { EXPECT_CALL(*http_server_props_manager_, ScheduleUpdatePrefsOnNetworkThread(_)) .WillRepeatedly(Invoke(http_server_props_manager_.get(), &TestingHttpServerPropertiesManager:: ScheduleUpdatePrefsOnNetworkThreadConcrete)); } void ExpectPrefsUpdate() { EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnNetworkThread(_)) .WillOnce(Invoke(http_server_props_manager_.get(), &TestingHttpServerPropertiesManager:: UpdatePrefsFromCacheOnNetworkThreadConcrete)); } void ExpectPrefsUpdateRepeatedly() { EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnNetworkThread(_)) .WillRepeatedly( Invoke(http_server_props_manager_.get(), &TestingHttpServerPropertiesManager:: UpdatePrefsFromCacheOnNetworkThreadConcrete)); } bool HasAlternativeService(const HostPortPair& server) { const AlternativeServiceVector alternative_service_vector = http_server_props_manager_->GetAlternativeServices(server); return !alternative_service_vector.empty(); } //base::RunLoop loop_; TestingPrefServiceSimple pref_service_; scoped_ptr http_server_props_manager_; base::Time one_day_from_now_; private: DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest); }; TEST_F(HttpServerPropertiesManagerTest, SingleUpdateForTwoSpdyServerPrefChanges) { ExpectCacheUpdate(); // Set up the prefs for www.google.com:80 and mail.google.com:80 and then set // it twice. Only expect a single cache update. base::DictionaryValue* server_pref_dict = new base::DictionaryValue; HostPortPair google_server("www.google.com", 80); HostPortPair mail_server("mail.google.com", 80); // Set supports_spdy for www.google.com:80. server_pref_dict->SetBoolean("supports_spdy", true); // Set up alternative_services for www.google.com:80. base::DictionaryValue* alternative_service_dict0 = new base::DictionaryValue; alternative_service_dict0->SetInteger("port", 443); alternative_service_dict0->SetString("protocol_str", "npn-h2"); base::DictionaryValue* alternative_service_dict1 = new base::DictionaryValue; alternative_service_dict1->SetInteger("port", 1234); alternative_service_dict1->SetString("protocol_str", "quic"); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict0); alternative_service_list->Append(alternative_service_dict1); server_pref_dict->SetWithoutPathExpansion("alternative_service", alternative_service_list); // Set up ServerNetworkStats for www.google.com:80. base::DictionaryValue* stats = new base::DictionaryValue; stats->SetInteger("srtt", 10); server_pref_dict->SetWithoutPathExpansion("network_stats", stats); // Set the server preference for www.google.com:80. base::DictionaryValue* servers_dict = new base::DictionaryValue; servers_dict->SetWithoutPathExpansion("www.google.com:80", server_pref_dict); // Set the preference for mail.google.com server. base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue; // Set supports_spdy for mail.google.com:80 server_pref_dict1->SetBoolean("supports_spdy", true); // Set up alternate_protocol for mail.google.com:80 to test migration to // alternative_service. base::DictionaryValue* alternate_protocol_dict = new base::DictionaryValue; alternate_protocol_dict->SetString("protocol_str", "npn-spdy/3.1"); alternate_protocol_dict->SetInteger("port", 444); server_pref_dict1->SetWithoutPathExpansion("alternate_protocol", alternate_protocol_dict); // Set up ServerNetworkStats for mail.google.com:80. base::DictionaryValue* stats1 = new base::DictionaryValue; stats1->SetInteger("srtt", 20); server_pref_dict1->SetWithoutPathExpansion("network_stats", stats1); // Set the server preference for mail.google.com:80. servers_dict->SetWithoutPathExpansion("mail.google.com:80", server_pref_dict1); base::DictionaryValue* http_server_properties_dict = new base::DictionaryValue; HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1); http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict); base::DictionaryValue* supports_quic = new base::DictionaryValue; supports_quic->SetBoolean("used_quic", true); supports_quic->SetString("address", "127.0.0.1"); http_server_properties_dict->SetWithoutPathExpansion("supports_quic", supports_quic); // Set quic_server_info for www.google.com:80 and mail.google.com:80. base::DictionaryValue* quic_servers_dict = new base::DictionaryValue; base::DictionaryValue* quic_server_pref_dict1 = new base::DictionaryValue; std::string quic_server_info1("quic_server_info1"); quic_server_pref_dict1->SetStringWithoutPathExpansion("server_info", quic_server_info1); base::DictionaryValue* quic_server_pref_dict2 = new base::DictionaryValue; std::string quic_server_info2("quic_server_info2"); quic_server_pref_dict2->SetStringWithoutPathExpansion("server_info", quic_server_info2); // Set the quic_server_info1 for www.google.com server. QuicServerId google_quic_server_id("www.google.com", 80); quic_servers_dict->SetWithoutPathExpansion(google_quic_server_id.ToString(), quic_server_pref_dict1); // Set the quic_server_info2 for mail.google.com server. QuicServerId mail_quic_server_id("mail.google.com", 80); quic_servers_dict->SetWithoutPathExpansion(mail_quic_server_id.ToString(), quic_server_pref_dict2); http_server_properties_dict->SetWithoutPathExpansion("quic_servers", quic_servers_dict); // Set the same value for kHttpServerProperties multiple times. pref_service_.SetManagedPref(kTestHttpServerProperties, http_server_properties_dict); base::DictionaryValue* http_server_properties_dict2 = http_server_properties_dict->DeepCopy(); pref_service_.SetManagedPref(kTestHttpServerProperties, http_server_properties_dict2); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); // Verify SupportsSpdy. EXPECT_TRUE( http_server_props_manager_->SupportsRequestPriority(google_server)); EXPECT_TRUE(http_server_props_manager_->SupportsRequestPriority(mail_server)); EXPECT_FALSE(http_server_props_manager_->SupportsRequestPriority( HostPortPair::FromString("foo.google.com:1337"))); // Verify alternative service. const AlternativeServiceMap& map = http_server_props_manager_->alternative_service_map(); ASSERT_EQ(2u, map.size()); AlternativeServiceMap::const_iterator map_it = map.begin(); EXPECT_EQ("www.google.com", map_it->first.host()); ASSERT_EQ(2u, map_it->second.size()); EXPECT_EQ(NPN_HTTP_2, map_it->second[0].alternative_service.protocol); EXPECT_TRUE(map_it->second[0].alternative_service.host.empty()); EXPECT_EQ(443, map_it->second[0].alternative_service.port); EXPECT_EQ(QUIC, map_it->second[1].alternative_service.protocol); EXPECT_TRUE(map_it->second[1].alternative_service.host.empty()); EXPECT_EQ(1234, map_it->second[1].alternative_service.port); ++map_it; EXPECT_EQ("mail.google.com", map_it->first.host()); ASSERT_EQ(1u, map_it->second.size()); EXPECT_EQ(NPN_SPDY_3_1, map_it->second[0].alternative_service.protocol); EXPECT_TRUE(map_it->second[0].alternative_service.host.empty()); EXPECT_EQ(444, map_it->second[0].alternative_service.port); // Verify SupportsQuic. IPAddressNumber last_address; EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&last_address)); EXPECT_EQ("127.0.0.1", IPAddressToString(last_address)); // Verify ServerNetworkStats. const ServerNetworkStats* stats2 = http_server_props_manager_->GetServerNetworkStats(google_server); EXPECT_EQ(10, stats2->srtt.ToInternalValue()); const ServerNetworkStats* stats3 = http_server_props_manager_->GetServerNetworkStats(mail_server); EXPECT_EQ(20, stats3->srtt.ToInternalValue()); // Verify QuicServerInfo. EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo( google_quic_server_id)); EXPECT_EQ(quic_server_info2, *http_server_props_manager_->GetQuicServerInfo( mail_quic_server_id)); } TEST_F(HttpServerPropertiesManagerTest, BadCachedHostPortPair) { ExpectCacheUpdate(); // The prefs are automaticalls updated in the case corruption is detected. ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); base::DictionaryValue* server_pref_dict = new base::DictionaryValue; // Set supports_spdy for www.google.com:65536. server_pref_dict->SetBoolean("supports_spdy", true); // Set up alternative_service for www.google.com:65536. base::DictionaryValue* alternative_service_dict = new base::DictionaryValue; alternative_service_dict->SetString("protocol_str", "npn-h2"); alternative_service_dict->SetInteger("port", 80); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict); server_pref_dict->SetWithoutPathExpansion("alternative_service", alternative_service_list); // Set up ServerNetworkStats for www.google.com:65536. base::DictionaryValue* stats = new base::DictionaryValue; stats->SetInteger("srtt", 10); server_pref_dict->SetWithoutPathExpansion("network_stats", stats); // Set the server preference for www.google.com:65536. base::DictionaryValue* servers_dict = new base::DictionaryValue; servers_dict->SetWithoutPathExpansion("www.google.com:65536", server_pref_dict); // Set quic_server_info for www.google.com:65536. base::DictionaryValue* quic_servers_dict = new base::DictionaryValue; base::DictionaryValue* quic_server_pref_dict1 = new base::DictionaryValue; quic_server_pref_dict1->SetStringWithoutPathExpansion("server_info", "quic_server_info1"); quic_servers_dict->SetWithoutPathExpansion("http://mail.google.com:65536", quic_server_pref_dict1); base::DictionaryValue* http_server_properties_dict = new base::DictionaryValue; HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1); http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict); http_server_properties_dict->SetWithoutPathExpansion("quic_servers", quic_servers_dict); // Set up the pref. pref_service_.SetManagedPref(kTestHttpServerProperties, http_server_properties_dict); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); // Verify that nothing is set. EXPECT_FALSE(http_server_props_manager_->SupportsRequestPriority( HostPortPair::FromString("www.google.com:65536"))); EXPECT_FALSE( HasAlternativeService(HostPortPair::FromString("www.google.com:65536"))); const ServerNetworkStats* stats1 = http_server_props_manager_->GetServerNetworkStats( HostPortPair::FromString("www.google.com:65536")); EXPECT_EQ(NULL, stats1); EXPECT_EQ(0u, http_server_props_manager_->quic_server_info_map().size()); } TEST_F(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) { ExpectCacheUpdate(); // The prefs are automaticalls updated in the case corruption is detected. ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); base::DictionaryValue* server_pref_dict = new base::DictionaryValue; // Set supports_spdy for www.google.com:80. server_pref_dict->SetBoolean("supports_spdy", true); // Set up alternative_service for www.google.com:80. base::DictionaryValue* alternative_service_dict = new base::DictionaryValue; alternative_service_dict->SetString("protocol_str", "npn-h2"); alternative_service_dict->SetInteger("port", 65536); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict); server_pref_dict->SetWithoutPathExpansion("alternative_service", alternative_service_list); // Set the server preference for www.google.com:80. base::DictionaryValue* servers_dict = new base::DictionaryValue; servers_dict->SetWithoutPathExpansion("www.google.com:80", server_pref_dict); base::DictionaryValue* http_server_properties_dict = new base::DictionaryValue; HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1); http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict); // Set up the pref. pref_service_.SetManagedPref(kTestHttpServerProperties, http_server_properties_dict); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); // Verify alternative service is not set. EXPECT_FALSE( HasAlternativeService(HostPortPair::FromString("www.google.com:80"))); } TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); // Post an update task to the network thread. SetSupportsSpdy calls // ScheduleUpdatePrefsOnNetworkThread. // Add mail.google.com:443 as a supporting spdy server. HostPortPair spdy_server_mail("mail.google.com", 443); EXPECT_FALSE( http_server_props_manager_->SupportsRequestPriority(spdy_server_mail)); http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true); // Run the task. base::RunLoop().RunUntilIdle(); EXPECT_TRUE( http_server_props_manager_->SupportsRequestPriority(spdy_server_mail)); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); } TEST_F(HttpServerPropertiesManagerTest, SetSpdySetting) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); // Add SpdySetting for mail.google.com:443. HostPortPair spdy_server_mail("mail.google.com", 443); const SpdySettingsIds id1 = SETTINGS_UPLOAD_BANDWIDTH; const SpdySettingsFlags flags1 = SETTINGS_FLAG_PLEASE_PERSIST; const uint32 value1 = 31337; http_server_props_manager_->SetSpdySetting( spdy_server_mail, id1, flags1, value1); // Run the task. base::RunLoop().RunUntilIdle(); const SettingsMap& settings_map1_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); ASSERT_EQ(1U, settings_map1_ret.size()); SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1); EXPECT_TRUE(it1_ret != settings_map1_ret.end()); SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second; EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first); EXPECT_EQ(value1, flags_and_value1_ret.second); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); } TEST_F(HttpServerPropertiesManagerTest, ClearSpdySetting) { ExpectPrefsUpdateRepeatedly(); ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(); // Add SpdySetting for mail.google.com:443. HostPortPair spdy_server_mail("mail.google.com", 443); const SpdySettingsIds id1 = SETTINGS_UPLOAD_BANDWIDTH; const SpdySettingsFlags flags1 = SETTINGS_FLAG_PLEASE_PERSIST; const uint32 value1 = 31337; http_server_props_manager_->SetSpdySetting( spdy_server_mail, id1, flags1, value1); // Run the task. base::RunLoop().RunUntilIdle(); const SettingsMap& settings_map1_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); ASSERT_EQ(1U, settings_map1_ret.size()); SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1); EXPECT_TRUE(it1_ret != settings_map1_ret.end()); SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second; EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first); EXPECT_EQ(value1, flags_and_value1_ret.second); // Clear SpdySetting for mail.google.com:443. http_server_props_manager_->ClearSpdySettings(spdy_server_mail); // Run the task. base::RunLoop().RunUntilIdle(); // Verify that there are no entries in the settings map for // mail.google.com:443. const SettingsMap& settings_map2_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); ASSERT_EQ(0U, settings_map2_ret.size()); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); } TEST_F(HttpServerPropertiesManagerTest, ClearAllSpdySetting) { ExpectPrefsUpdateRepeatedly(); ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(); // Add SpdySetting for mail.google.com:443. HostPortPair spdy_server_mail("mail.google.com", 443); const SpdySettingsIds id1 = SETTINGS_UPLOAD_BANDWIDTH; const SpdySettingsFlags flags1 = SETTINGS_FLAG_PLEASE_PERSIST; const uint32 value1 = 31337; http_server_props_manager_->SetSpdySetting( spdy_server_mail, id1, flags1, value1); // Run the task. base::RunLoop().RunUntilIdle(); const SettingsMap& settings_map1_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); ASSERT_EQ(1U, settings_map1_ret.size()); SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1); EXPECT_TRUE(it1_ret != settings_map1_ret.end()); SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second; EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first); EXPECT_EQ(value1, flags_and_value1_ret.second); // Clear All SpdySettings. http_server_props_manager_->ClearAllSpdySettings(); // Run the task. base::RunLoop().RunUntilIdle(); // Verify that there are no entries in the settings map. const SpdySettingsMap& spdy_settings_map2_ret = http_server_props_manager_->spdy_settings_map(); ASSERT_EQ(0U, spdy_settings_map2_ret.size()); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); } TEST_F(HttpServerPropertiesManagerTest, GetAlternativeServices) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); HostPortPair spdy_server_mail("mail.google.com", 80); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); const AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); http_server_props_manager_->SetAlternativeService( spdy_server_mail, alternative_service, 1.0, one_day_from_now_); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->SetAlternativeService( spdy_server_mail, alternative_service, 1.0, one_day_from_now_); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); AlternativeServiceVector alternative_service_vector = http_server_props_manager_->GetAlternativeServices(spdy_server_mail); ASSERT_EQ(1u, alternative_service_vector.size()); EXPECT_EQ(alternative_service, alternative_service_vector[0]); } TEST_F(HttpServerPropertiesManagerTest, SetAlternativeServices) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); HostPortPair spdy_server_mail("mail.google.com", 80); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); AlternativeServiceInfoVector alternative_service_info_vector; const AlternativeService alternative_service1(NPN_HTTP_2, "mail.google.com", 443); alternative_service_info_vector.push_back( AlternativeServiceInfo(alternative_service1, 1.0, one_day_from_now_)); const AlternativeService alternative_service2(QUIC, "mail.google.com", 1234); alternative_service_info_vector.push_back( AlternativeServiceInfo(alternative_service2, 1.0, one_day_from_now_)); http_server_props_manager_->SetAlternativeServices( spdy_server_mail, alternative_service_info_vector); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->SetAlternativeServices( spdy_server_mail, alternative_service_info_vector); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); AlternativeServiceVector alternative_service_vector = http_server_props_manager_->GetAlternativeServices(spdy_server_mail); ASSERT_EQ(2u, alternative_service_vector.size()); EXPECT_EQ(alternative_service1, alternative_service_vector[0]); EXPECT_EQ(alternative_service2, alternative_service_vector[1]); } TEST_F(HttpServerPropertiesManagerTest, SetAlternativeServicesEmpty) { HostPortPair spdy_server_mail("mail.google.com", 80); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); const AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); http_server_props_manager_->SetAlternativeServices( spdy_server_mail, AlternativeServiceInfoVector()); // ExpectScheduleUpdatePrefsOnNetworkThread() should not be called. // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); } TEST_F(HttpServerPropertiesManagerTest, ClearAlternativeServices) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); HostPortPair spdy_server_mail("mail.google.com", 80); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); http_server_props_manager_->SetAlternativeService( spdy_server_mail, alternative_service, 1.0, one_day_from_now_); ExpectScheduleUpdatePrefsOnNetworkThread(); http_server_props_manager_->ClearAlternativeServices(spdy_server_mail); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->ClearAlternativeServices(spdy_server_mail); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); } TEST_F(HttpServerPropertiesManagerTest, ConfirmAlternativeService) { ExpectPrefsUpdate(); HostPortPair spdy_server_mail("mail.google.com", 80); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); ExpectScheduleUpdatePrefsOnNetworkThread(); http_server_props_manager_->SetAlternativeService( spdy_server_mail, alternative_service, 1.0, one_day_from_now_); EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken( alternative_service)); EXPECT_FALSE(http_server_props_manager_->WasAlternativeServiceRecentlyBroken( alternative_service)); ExpectScheduleUpdatePrefsOnNetworkThread(); http_server_props_manager_->MarkAlternativeServiceBroken(alternative_service); EXPECT_TRUE(http_server_props_manager_->IsAlternativeServiceBroken( alternative_service)); EXPECT_TRUE(http_server_props_manager_->WasAlternativeServiceRecentlyBroken( alternative_service)); ExpectScheduleUpdatePrefsOnNetworkThread(); http_server_props_manager_->ConfirmAlternativeService(alternative_service); EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken( alternative_service)); EXPECT_FALSE(http_server_props_manager_->WasAlternativeServiceRecentlyBroken( alternative_service)); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->ConfirmAlternativeService(alternative_service); EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken( alternative_service)); EXPECT_FALSE(http_server_props_manager_->WasAlternativeServiceRecentlyBroken( alternative_service)); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken( alternative_service)); EXPECT_FALSE(http_server_props_manager_->WasAlternativeServiceRecentlyBroken( alternative_service)); } TEST_F(HttpServerPropertiesManagerTest, SupportsQuic) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); IPAddressNumber address; EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address)); IPAddressNumber actual_address; CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address)); http_server_props_manager_->SetSupportsQuic(true, actual_address); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->SetSupportsQuic(true, actual_address); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address)); EXPECT_EQ(actual_address, address); } TEST_F(HttpServerPropertiesManagerTest, ServerNetworkStats) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); HostPortPair mail_server("mail.google.com", 80); const ServerNetworkStats* stats = http_server_props_manager_->GetServerNetworkStats(mail_server); EXPECT_EQ(NULL, stats); ServerNetworkStats stats1; stats1.srtt = base::TimeDelta::FromMicroseconds(10); http_server_props_manager_->SetServerNetworkStats(mail_server, stats1); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->SetServerNetworkStats(mail_server, stats1); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); const ServerNetworkStats* stats2 = http_server_props_manager_->GetServerNetworkStats(mail_server); EXPECT_EQ(10, stats2->srtt.ToInternalValue()); } TEST_F(HttpServerPropertiesManagerTest, QuicServerInfo) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThread(); QuicServerId mail_quic_server_id("mail.google.com", 80); EXPECT_EQ(nullptr, http_server_props_manager_->GetQuicServerInfo(mail_quic_server_id)); std::string quic_server_info1("quic_server_info1"); http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, quic_server_info1); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, quic_server_info1); // Run the task. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo( mail_quic_server_id)); } TEST_F(HttpServerPropertiesManagerTest, Clear) { ExpectPrefsUpdate(); ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(); HostPortPair spdy_server_mail("mail.google.com", 443); http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true); AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 1234); http_server_props_manager_->SetAlternativeService( spdy_server_mail, alternative_service, 1.0, one_day_from_now_); IPAddressNumber actual_address; CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address)); http_server_props_manager_->SetSupportsQuic(true, actual_address); ServerNetworkStats stats; stats.srtt = base::TimeDelta::FromMicroseconds(10); http_server_props_manager_->SetServerNetworkStats(spdy_server_mail, stats); QuicServerId mail_quic_server_id("mail.google.com", 80); std::string quic_server_info1("quic_server_info1"); http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, quic_server_info1); const SpdySettingsIds id1 = SETTINGS_UPLOAD_BANDWIDTH; const SpdySettingsFlags flags1 = SETTINGS_FLAG_PLEASE_PERSIST; const uint32 value1 = 31337; http_server_props_manager_->SetSpdySetting(spdy_server_mail, id1, flags1, value1); // Run the task. base::RunLoop().RunUntilIdle(); EXPECT_TRUE( http_server_props_manager_->SupportsRequestPriority(spdy_server_mail)); EXPECT_TRUE(HasAlternativeService(spdy_server_mail)); IPAddressNumber address; EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address)); EXPECT_EQ(actual_address, address); const ServerNetworkStats* stats1 = http_server_props_manager_->GetServerNetworkStats(spdy_server_mail); EXPECT_EQ(10, stats1->srtt.ToInternalValue()); EXPECT_EQ(quic_server_info1, *http_server_props_manager_->GetQuicServerInfo( mail_quic_server_id)); // Check SPDY settings values. const SettingsMap& settings_map1_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); ASSERT_EQ(1U, settings_map1_ret.size()); SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1); EXPECT_TRUE(it1_ret != settings_map1_ret.end()); SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second; EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first); EXPECT_EQ(value1, flags_and_value1_ret.second); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); ExpectPrefsUpdate(); // Clear http server data, time out if we do not get a completion callback. http_server_props_manager_->Clear(base::MessageLoop::QuitWhenIdleClosure()); base::RunLoop().Run(); EXPECT_FALSE( http_server_props_manager_->SupportsRequestPriority(spdy_server_mail)); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address)); const ServerNetworkStats* stats2 = http_server_props_manager_->GetServerNetworkStats(spdy_server_mail); EXPECT_EQ(NULL, stats2); EXPECT_EQ(nullptr, http_server_props_manager_->GetQuicServerInfo(mail_quic_server_id)); const SettingsMap& settings_map2_ret = http_server_props_manager_->GetSpdySettings(spdy_server_mail); EXPECT_EQ(0U, settings_map2_ret.size()); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); } // https://crbug.com/444956: Add 200 alternative_service servers followed by // supports_quic and verify we have read supports_quic from prefs. TEST_F(HttpServerPropertiesManagerTest, BadSupportsQuic) { ExpectCacheUpdate(); base::DictionaryValue* servers_dict = new base::DictionaryValue; for (int i = 0; i < 200; ++i) { // Set up alternative_service for www.google.com:i. base::DictionaryValue* alternative_service_dict = new base::DictionaryValue; alternative_service_dict->SetString("protocol_str", "quic"); alternative_service_dict->SetInteger("port", i); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict); base::DictionaryValue* server_pref_dict = new base::DictionaryValue; server_pref_dict->SetWithoutPathExpansion("alternative_service", alternative_service_list); servers_dict->SetWithoutPathExpansion(StringPrintf("www.google.com:%d", i), server_pref_dict); } // Set the preference for mail.google.com server. base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue; // Set the server preference for mail.google.com:80. servers_dict->SetWithoutPathExpansion("mail.google.com:80", server_pref_dict1); base::DictionaryValue* http_server_properties_dict = new base::DictionaryValue; HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1); http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict); // Set up SupportsQuic for 127.0.0.1 base::DictionaryValue* supports_quic = new base::DictionaryValue; supports_quic->SetBoolean("used_quic", true); supports_quic->SetString("address", "127.0.0.1"); http_server_properties_dict->SetWithoutPathExpansion("supports_quic", supports_quic); // Set up the pref. pref_service_.SetManagedPref(kTestHttpServerProperties, http_server_properties_dict); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); // Verify alternative service. for (int i = 0; i < 200; ++i) { std::string server = StringPrintf("www.google.com:%d", i); AlternativeServiceVector alternative_service_vector = http_server_props_manager_->GetAlternativeServices( HostPortPair::FromString(server)); ASSERT_EQ(1u, alternative_service_vector.size()); EXPECT_EQ(QUIC, alternative_service_vector[0].protocol); EXPECT_EQ(i, alternative_service_vector[0].port); } // Verify SupportsQuic. IPAddressNumber address; ASSERT_TRUE(http_server_props_manager_->GetSupportsQuic(&address)); EXPECT_EQ("127.0.0.1", IPAddressToString(address)); } TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) { ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(); const HostPortPair server_www("www.google.com", 80); const HostPortPair server_mail("mail.google.com", 80); // Set alternate protocol. AlternativeServiceInfoVector alternative_service_info_vector; AlternativeService www_alternative_service1(NPN_HTTP_2, "", 443); base::Time expiration1; ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1)); alternative_service_info_vector.push_back( AlternativeServiceInfo(www_alternative_service1, 1.0, expiration1)); AlternativeService www_alternative_service2(NPN_HTTP_2, "www.google.com", 1234); base::Time expiration2; ASSERT_TRUE(base::Time::FromUTCString("2036-12-31 10:00:00", &expiration2)); alternative_service_info_vector.push_back( AlternativeServiceInfo(www_alternative_service2, 0.7, expiration2)); http_server_props_manager_->SetAlternativeServices( server_www, alternative_service_info_vector); AlternativeService mail_alternative_service(NPN_SPDY_3_1, "foo.google.com", 444); base::Time expiration3 = base::Time::Max(); http_server_props_manager_->SetAlternativeService( server_mail, mail_alternative_service, 0.2, expiration3); // Set ServerNetworkStats. ServerNetworkStats stats; stats.srtt = base::TimeDelta::FromInternalValue(42); http_server_props_manager_->SetServerNetworkStats(server_mail, stats); // Set quic_server_info string. QuicServerId mail_quic_server_id("mail.google.com", 80); std::string quic_server_info1("quic_server_info1"); http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id, quic_server_info1); // Set SupportsQuic. IPAddressNumber actual_address; CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address)); http_server_props_manager_->SetSupportsQuic(true, actual_address); // Update cache. ExpectPrefsUpdate(); ExpectCacheUpdate(); http_server_props_manager_->ScheduleUpdateCacheOnPrefThread(); base::RunLoop().RunUntilIdle(); // Verify preferences. const char expected_json[] = "{\"quic_servers\":{\"https://" "mail.google.com:80\":{\"server_info\":\"quic_server_info1\"}}," "\"servers\":{\"mail.google.com:80\":{\"alternative_service\":[{" "\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\"," "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\"}]," "\"network_stats\":{\"srtt\":42}},\"www.google.com:80\":{" "\"alternative_service\":[{\"expiration\":\"13756212000000000\"," "\"port\":443,\"probability\":1.0,\"protocol_str\":\"npn-h2\"}," "{\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\"," "\"port\":1234,\"probability\":0.7,\"protocol_str\":\"npn-h2\"}]}}," "\"supports_quic\":{\"address\":\"127.0.0.1\",\"used_quic\":true}," "\"version\":3}"; const base::Value* http_server_properties = pref_service_.GetUserPref(kTestHttpServerProperties); ASSERT_NE(nullptr, http_server_properties); std::string preferences_json; EXPECT_TRUE( base::JSONWriter::Write(*http_server_properties, &preferences_json)); EXPECT_EQ(expected_json, preferences_json); } TEST_F(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) { scoped_ptr server_value = base::JSONReader::Read( "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"}," "{\"port\":123,\"protocol_str\":\"quic\",\"probability\":0.7," "\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\"," "\"port\":1234,\"protocol_str\":\"npn-h2\",\"probability\":0.2," "\"expiration\":\"13758804000000000\"}]}"); ASSERT_TRUE(server_value); base::DictionaryValue* server_dict; ASSERT_TRUE(server_value->GetAsDictionary(&server_dict)); const HostPortPair host_port_pair("example.com", 443); AlternativeServiceMap alternative_service_map(/*max_size=*/5); EXPECT_TRUE(http_server_props_manager_->AddToAlternativeServiceMap( host_port_pair, *server_dict, &alternative_service_map)); AlternativeServiceMap::iterator it = alternative_service_map.Get(host_port_pair); ASSERT_NE(alternative_service_map.end(), it); AlternativeServiceInfoVector alternative_service_info_vector = it->second; ASSERT_EQ(3u, alternative_service_info_vector.size()); EXPECT_EQ(NPN_HTTP_2, alternative_service_info_vector[0].alternative_service.protocol); EXPECT_EQ("", alternative_service_info_vector[0].alternative_service.host); EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port); // Probability defaults to 1.0. EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability); // Expiration defaults to one day from now, testing with tolerance. const base::Time now = base::Time::Now(); const base::Time expiration = alternative_service_info_vector[0].expiration; EXPECT_LE(now + base::TimeDelta::FromHours(23), expiration); EXPECT_GE(now + base::TimeDelta::FromDays(1), expiration); EXPECT_EQ(QUIC, alternative_service_info_vector[1].alternative_service.protocol); EXPECT_EQ("", alternative_service_info_vector[1].alternative_service.host); EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service.port); EXPECT_DOUBLE_EQ(0.7, alternative_service_info_vector[1].probability); // numeric_limits::max() represents base::Time::Max(). EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration); EXPECT_EQ(NPN_HTTP_2, alternative_service_info_vector[2].alternative_service.protocol); EXPECT_EQ("example.org", alternative_service_info_vector[2].alternative_service.host); EXPECT_EQ(1234, alternative_service_info_vector[2].alternative_service.port); EXPECT_DOUBLE_EQ(0.2, alternative_service_info_vector[2].probability); base::Time expected_expiration; ASSERT_TRUE( base::Time::FromUTCString("2036-12-31 10:00:00", &expected_expiration)); EXPECT_EQ(expected_expiration, alternative_service_info_vector[2].expiration); } // Early release 46 Dev and Canary builds serialized alternative service // expiration as double. Test that they are properly parsed. // TODO(bnc) Remove this test around 2015-10-01, // and remove corresponding FRIEND macro from header file. TEST_F(HttpServerPropertiesManagerTest, AlternativeServiceExpirationDouble) { scoped_ptr server_value = base::JSONReader::Read( "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"," "\"expiration\":1234567890.0}]}"); ASSERT_TRUE(server_value); base::DictionaryValue* server_dict; ASSERT_TRUE(server_value->GetAsDictionary(&server_dict)); const HostPortPair host_port_pair("example.com", 443); AlternativeServiceMap alternative_service_map(/*max_size=*/5); EXPECT_TRUE(http_server_props_manager_->AddToAlternativeServiceMap( host_port_pair, *server_dict, &alternative_service_map)); AlternativeServiceMap::iterator it = alternative_service_map.Get(host_port_pair); ASSERT_NE(alternative_service_map.end(), it); AlternativeServiceInfoVector alternative_service_info_vector = it->second; ASSERT_EQ(1u, alternative_service_info_vector.size()); EXPECT_EQ(NPN_HTTP_2, alternative_service_info_vector[0].alternative_service.protocol); EXPECT_EQ("", alternative_service_info_vector[0].alternative_service.host); EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port); // Probability defaults to 1.0. EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability); base::Time expected_expiration; ASSERT_TRUE( base::Time::FromUTCString("2009-02-13 23:31:30", &expected_expiration)); EXPECT_EQ(expected_expiration, alternative_service_info_vector[0].expiration); } TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) { // Post an update task to the UI thread. http_server_props_manager_->ScheduleUpdateCacheOnPrefThread(); // Shutdown comes before the task is executed. http_server_props_manager_->ShutdownOnPrefThread(); http_server_props_manager_.reset(); // Run the task after shutdown and deletion. base::RunLoop().RunUntilIdle(); } TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) { // Post an update task. http_server_props_manager_->ScheduleUpdateCacheOnPrefThread(); // Shutdown comes before the task is executed. http_server_props_manager_->ShutdownOnPrefThread(); // Run the task after shutdown, but before deletion. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); http_server_props_manager_.reset(); base::RunLoop().RunUntilIdle(); } TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) { http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete(); // Shutdown comes before the task is executed. http_server_props_manager_->ShutdownOnPrefThread(); // Run the task after shutdown, but before deletion. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); http_server_props_manager_.reset(); base::RunLoop().RunUntilIdle(); } // // Tests for shutdown when updating prefs. // TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) { // Post an update task to the IO thread. http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThread(); // Shutdown comes before the task is executed. http_server_props_manager_->ShutdownOnPrefThread(); http_server_props_manager_.reset(); // Run the task after shutdown and deletion. base::RunLoop().RunUntilIdle(); } TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) { ExpectPrefsUpdate(); // Post an update task. http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThread(); // Shutdown comes before the task is executed. http_server_props_manager_->ShutdownOnPrefThread(); // Run the task after shutdown, but before deletion. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); http_server_props_manager_.reset(); base::RunLoop().RunUntilIdle(); } TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) { // This posts a task to the UI thread. http_server_props_manager_->UpdatePrefsFromCacheOnNetworkThreadConcrete( base::Closure()); // Shutdown comes before the task is executed. http_server_props_manager_->ShutdownOnPrefThread(); // Run the task after shutdown, but before deletion. base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(http_server_props_manager_.get()); http_server_props_manager_.reset(); base::RunLoop().RunUntilIdle(); } } // namespace net