// 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_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/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/test_simple_task_runner.h"
#include "base/values.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<base::SingleThreadTaskRunner> io_task_runner)
      : HttpServerPropertiesManager(pref_service, pref_path, io_task_runner) {
    InitializeOnNetworkThread();
  }

  ~TestingHttpServerPropertiesManager() override {}

  // Make these methods public for testing.
  using HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread;
  using HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread;

  // 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 ScheduleUpdatePrefsOnNetworkThread() {
    // Picked a random Location as caller.
    HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(
        DETECTED_CORRUPTED_PREFS);
  }

  MOCK_METHOD0(UpdateCacheFromPrefsOnPrefThread, void());
  MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkThread, void(const base::Closure&));
  MOCK_METHOD6(UpdateCacheFromPrefsOnNetworkThread,
               void(std::vector<std::string>* spdy_servers,
                    SpdySettingsMap* spdy_settings_map,
                    AlternativeServiceMap* alternative_service_map,
                    IPAddressNumber* last_quic_address,
                    ServerNetworkStatsMap* server_network_stats_map,
                    bool detected_corrupted_prefs));
  MOCK_METHOD5(UpdatePrefsOnPref,
               void(base::ListValue* spdy_server_list,
                    SpdySettingsMap* spdy_settings_map,
                    AlternativeServiceMap* alternative_service_map,
                    IPAddressNumber* last_quic_address,
                    ServerNetworkStatsMap* server_network_stats_map));

 private:
  DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager);
};

class HttpServerPropertiesManagerTest : public testing::Test {
 protected:
  HttpServerPropertiesManagerTest() {}

  void SetUp() override {
    pref_service_.registry()->RegisterDictionaryPref(kTestHttpServerProperties);
    http_server_props_manager_.reset(
        new StrictMock<TestingHttpServerPropertiesManager>(
            &pref_service_, kTestHttpServerProperties,
            base::MessageLoop::current()->task_runner()));
    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 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 AlternativeService alternative_service =
        http_server_props_manager_->GetAlternativeService(server);
    return alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL;
  }

  //base::RunLoop loop_;
  TestingPrefServiceSimple pref_service_;
  scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;

 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_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->SetString("host", "maps.google.com");
  alternative_service_dict->SetInteger("port", 443);
  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: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 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.
  AlternativeService alternative_service =
      http_server_props_manager_->GetAlternativeService(google_server);
  EXPECT_EQ(NPN_SPDY_4, alternative_service.protocol);
  EXPECT_EQ("maps.google.com", alternative_service.host);
  EXPECT_EQ(443, alternative_service.port);
  alternative_service =
      http_server_props_manager_->GetAlternativeService(mail_server);
  EXPECT_EQ(NPN_SPDY_3_1, alternative_service.protocol);
  EXPECT_EQ("mail.google.com", alternative_service.host);
  EXPECT_EQ(444, 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());
}

TEST_F(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
  ExpectCacheUpdate();
  // The prefs are automaticalls updated in the case corruption is detected.
  ExpectPrefsUpdate();

  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-spdy/3");
  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);

  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 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);
}

TEST_F(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
  ExpectCacheUpdate();
  // The prefs are automaticalls updated in the case corruption is detected.
  ExpectPrefsUpdate();

  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-spdy/3");
  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();

  // 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);

  // 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();

  // 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();

  // 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();

  // 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, GetAlternativeService) {
  ExpectPrefsUpdate();

  HostPortPair spdy_server_mail("mail.google.com", 80);
  EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
  AlternativeService alternative_service(NPN_SPDY_4, "mail.google.com", 443);
  http_server_props_manager_->SetAlternativeService(spdy_server_mail,
                                                    alternative_service, 1.0);

  // Run the task.
  base::RunLoop().RunUntilIdle();
  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());

  alternative_service =
      http_server_props_manager_->GetAlternativeService(spdy_server_mail);
  EXPECT_EQ(443, alternative_service.port);
  EXPECT_EQ(NPN_SPDY_4, alternative_service.protocol);
}

TEST_F(HttpServerPropertiesManagerTest, SupportsQuic) {
  ExpectPrefsUpdate();

  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);

  // 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();

  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);

  // 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, Clear) {
  ExpectPrefsUpdate();

  HostPortPair spdy_server_mail("mail.google.com", 443);
  http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
  AlternativeService alternative_service(NPN_SPDY_4, "mail.google.com", 443);
  http_server_props_manager_->SetAlternativeService(spdy_server_mail,
                                                    alternative_service, 1.0);
  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);

  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());

  // 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::QuitClosure());
  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);

  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", "npn-h2");
    alternative_service_dict->SetString("host", "");
    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);
    AlternativeService alternative_service =
        http_server_props_manager_->GetAlternativeService(
            HostPortPair::FromString(server));
    EXPECT_EQ(i, alternative_service.port);
    EXPECT_EQ(NPN_SPDY_4, alternative_service.protocol);
  }

  // Verify SupportsQuic.
  IPAddressNumber address;
  ASSERT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
  EXPECT_EQ("127.0.0.1", IPAddressToString(address));
}

TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
  const HostPortPair server_www("www.google.com", 80);
  const HostPortPair server_mail("mail.google.com", 80);

  // Set alternate protocol.
  AlternativeService www_altsvc(NPN_SPDY_4, "", 443);
  AlternativeService mail_altsvc(NPN_SPDY_3_1, "mail.google.com", 444);
  http_server_props_manager_->SetAlternativeService(server_www, www_altsvc,
                                                    1.0);
  http_server_props_manager_->SetAlternativeService(server_mail, mail_altsvc,
                                                    0.2);

  // Set ServerNetworkStats.
  ServerNetworkStats stats;
  stats.srtt = base::TimeDelta::FromInternalValue(42);
  http_server_props_manager_->SetServerNetworkStats(server_mail, stats);

  // 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[] =
      "{\"servers\":{\"mail.google.com:80\":{\"alternative_service\":[{"
      "\"host\":"
      "\"mail.google.com\",\"port\":444,\"probability\":0.2,\"protocol_str\":"
      "\"npn-spdy/"
      "3.1\"}],\"network_stats\":{\"srtt\":42}},\"www.google.com:80\":"
      "{\"alternative_service\":[{\"port\":443,\"probability\":1.0,"
      "\"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, 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

}  // namespace net
