// Copyright (c) 2012 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.h"

#include <memory>
#include <string>
#include <vector>

#include "base/bind.h"
#include "base/check.h"
#include "base/feature_list.h"
#include "base/json/json_writer.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "net/base/features.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/schemeful_site.h"
#include "net/http/http_network_session.h"
#include "net/test/test_with_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace net {

const base::TimeDelta BROKEN_ALT_SVC_EXPIRE_DELAYS[10] = {
    base::TimeDelta::FromSeconds(300),   base::TimeDelta::FromSeconds(600),
    base::TimeDelta::FromSeconds(1200),  base::TimeDelta::FromSeconds(2400),
    base::TimeDelta::FromSeconds(4800),  base::TimeDelta::FromSeconds(9600),
    base::TimeDelta::FromSeconds(19200), base::TimeDelta::FromSeconds(38400),
    base::TimeDelta::FromSeconds(76800), base::TimeDelta::FromSeconds(153600),
};

class HttpServerPropertiesPeer {
 public:
  static void AddBrokenAlternativeServiceWithExpirationTime(
      HttpServerProperties* impl,
      const AlternativeService& alternative_service,
      base::TimeTicks when,
      const NetworkIsolationKey network_isolation_key = NetworkIsolationKey()) {
    BrokenAlternativeService broken_alternative_service(
        alternative_service, network_isolation_key,
        true /* use_network_isolation_key */);
    BrokenAlternativeServiceList::iterator unused_it;
    impl->broken_alternative_services_.AddToBrokenListAndMap(
        broken_alternative_service, when, &unused_it);
    auto it =
        impl->broken_alternative_services_.recently_broken_alternative_services_
            .Get(broken_alternative_service);
    if (it == impl->broken_alternative_services_
                  .recently_broken_alternative_services_.end()) {
      impl->broken_alternative_services_.recently_broken_alternative_services_
          .Put(broken_alternative_service, 1);
    } else {
      it->second++;
    }
  }

  static void ExpireBrokenAlternateProtocolMappings(
      HttpServerProperties* impl) {
    impl->broken_alternative_services_.ExpireBrokenAlternateProtocolMappings();
  }
};

namespace {

// Creates a ServerInfoMapKey without a NetworkIsolationKey.
HttpServerProperties::ServerInfoMapKey CreateSimpleKey(
    const url::SchemeHostPort& server) {
  return HttpServerProperties::ServerInfoMapKey(
      server, net::NetworkIsolationKey(),
      false /* use_network_isolation_key */);
}

class HttpServerPropertiesTest : public TestWithTaskEnvironment {
 protected:
  HttpServerPropertiesTest()
      : TestWithTaskEnvironment(
            base::test::TaskEnvironment::TimeSource::MOCK_TIME),
        // Many tests assume partitioning is disabled by default.
        feature_list_(CreateFeatureListWithPartitioningDisabled()),
        test_tick_clock_(GetMockTickClock()),
        impl_(nullptr /* pref_delegate */,
              nullptr /* net_log */,
              test_tick_clock_,
              &test_clock_) {
    // Set |test_clock_| to some random time.
    test_clock_.Advance(base::TimeDelta::FromSeconds(12345));

    SchemefulSite site1(GURL("https://foo.test/"));
    network_isolation_key1_ = NetworkIsolationKey(site1, site1);
    SchemefulSite site2(GURL("https://bar.test/"));
    network_isolation_key2_ = NetworkIsolationKey(site2, site2);
  }

  // This is a little awkward, but need to create and configure the
  // ScopedFeatureList before creating the HttpServerProperties.
  static std::unique_ptr<base::test::ScopedFeatureList>
  CreateFeatureListWithPartitioningDisabled() {
    std::unique_ptr<base::test::ScopedFeatureList> feature_list =
        std::make_unique<base::test::ScopedFeatureList>();
    feature_list->InitAndDisableFeature(
        features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
    return feature_list;
  }

  bool HasAlternativeService(const url::SchemeHostPort& origin,
                             const NetworkIsolationKey& network_isolation_key) {
    const AlternativeServiceInfoVector alternative_service_info_vector =
        impl_.GetAlternativeServiceInfos(origin, network_isolation_key);
    return !alternative_service_info_vector.empty();
  }

  void SetAlternativeService(const url::SchemeHostPort& origin,
                             const AlternativeService& alternative_service) {
    const base::Time expiration =
        test_clock_.Now() + base::TimeDelta::FromDays(1);
    if (alternative_service.protocol == kProtoQUIC) {
      impl_.SetQuicAlternativeService(origin, NetworkIsolationKey(),
                                      alternative_service, expiration,
                                      DefaultSupportedQuicVersions());
    } else {
      impl_.SetHttp2AlternativeService(origin, NetworkIsolationKey(),
                                       alternative_service, expiration);
    }
  }

  void MarkBrokenAndLetExpireAlternativeServiceNTimes(
      const AlternativeService& alternative_service,
      int num_times) {}

  std::unique_ptr<base::test::ScopedFeatureList> feature_list_;

  const base::TickClock* test_tick_clock_;
  base::SimpleTestClock test_clock_;

  // Two different non-empty network isolation keys for use in tests that need
  // them.
  NetworkIsolationKey network_isolation_key1_;
  NetworkIsolationKey network_isolation_key2_;

  HttpServerProperties impl_;
};

TEST_F(HttpServerPropertiesTest, SetSupportsSpdy) {
  // Check spdy servers are correctly set with SchemeHostPort key.
  url::SchemeHostPort https_www_server("https", "www.google.com", 443);
  url::SchemeHostPort http_photo_server("http", "photos.google.com", 80);
  url::SchemeHostPort https_mail_server("https", "mail.google.com", 443);
  // Servers with port equal to default port in scheme will drop port components
  // when calling Serialize().

  url::SchemeHostPort http_google_server("http", "www.google.com", 443);
  url::SchemeHostPort https_photos_server("https", "photos.google.com", 443);
  url::SchemeHostPort valid_google_server((GURL("https://www.google.com")));

  impl_.SetSupportsSpdy(https_www_server, NetworkIsolationKey(), true);
  impl_.SetSupportsSpdy(http_photo_server, NetworkIsolationKey(), true);
  impl_.SetSupportsSpdy(https_mail_server, NetworkIsolationKey(), false);
  EXPECT_TRUE(impl_.GetSupportsSpdy(https_www_server, NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(https_www_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(http_photo_server, NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(http_photo_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(https_mail_server, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.SupportsRequestPriority(https_mail_server, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.GetSupportsSpdy(http_google_server, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.SupportsRequestPriority(http_google_server, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.GetSupportsSpdy(https_photos_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.SupportsRequestPriority(https_photos_server,
                                             NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.GetSupportsSpdy(valid_google_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.SupportsRequestPriority(valid_google_server,
                                            NetworkIsolationKey()));

  // Flip values of two servers.
  impl_.SetSupportsSpdy(https_www_server, NetworkIsolationKey(), false);
  impl_.SetSupportsSpdy(https_mail_server, NetworkIsolationKey(), true);
  EXPECT_FALSE(impl_.GetSupportsSpdy(https_www_server, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.SupportsRequestPriority(https_www_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(https_mail_server, NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(https_mail_server, NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, SetSupportsSpdyWebSockets) {
  // The https and wss servers should be treated as the same server, as should
  // the http and ws servers.
  url::SchemeHostPort https_server("https", "www.test.com", 443);
  url::SchemeHostPort wss_server("wss", "www.test.com", 443);
  url::SchemeHostPort http_server("http", "www.test.com", 443);
  url::SchemeHostPort ws_server("ws", "www.test.com", 443);

  EXPECT_FALSE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));

  impl_.SetSupportsSpdy(wss_server, NetworkIsolationKey(), true);
  EXPECT_TRUE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));

  impl_.SetSupportsSpdy(http_server, NetworkIsolationKey(), true);
  EXPECT_TRUE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));

  impl_.SetSupportsSpdy(https_server, NetworkIsolationKey(), false);
  EXPECT_FALSE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));

  impl_.SetSupportsSpdy(ws_server, NetworkIsolationKey(), false);
  EXPECT_FALSE(impl_.GetSupportsSpdy(https_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(wss_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(http_server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(ws_server, NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, SetSupportsSpdyWithNetworkIsolationKey) {
  const url::SchemeHostPort kServer("https", "foo.test", 443);

  EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, network_isolation_key1_));
  EXPECT_FALSE(impl_.SupportsRequestPriority(kServer, network_isolation_key1_));
  EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.SupportsRequestPriority(kServer, NetworkIsolationKey()));

  // Without network isolation keys enabled for HttpServerProperties, passing in
  // a NetworkIsolationKey should have no effect on behavior.
  for (const auto& network_isolation_key_to_set :
       {NetworkIsolationKey(), network_isolation_key1_}) {
    impl_.SetSupportsSpdy(kServer, network_isolation_key_to_set, true);
    EXPECT_TRUE(impl_.GetSupportsSpdy(kServer, network_isolation_key1_));
    EXPECT_TRUE(
        impl_.SupportsRequestPriority(kServer, network_isolation_key1_));
    EXPECT_TRUE(impl_.GetSupportsSpdy(kServer, NetworkIsolationKey()));
    EXPECT_TRUE(impl_.SupportsRequestPriority(kServer, NetworkIsolationKey()));

    impl_.SetSupportsSpdy(kServer, network_isolation_key_to_set, false);
    EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, network_isolation_key1_));
    EXPECT_FALSE(
        impl_.SupportsRequestPriority(kServer, network_isolation_key1_));
    EXPECT_FALSE(impl_.GetSupportsSpdy(kServer, NetworkIsolationKey()));
    EXPECT_FALSE(impl_.SupportsRequestPriority(kServer, NetworkIsolationKey()));
  }

  // With network isolation keys enabled for HttpServerProperties, the
  // NetworkIsolationKey argument should be respected.

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  EXPECT_FALSE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
  EXPECT_FALSE(
      properties.SupportsRequestPriority(kServer, network_isolation_key1_));
  EXPECT_FALSE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
  EXPECT_FALSE(
      properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));

  properties.SetSupportsSpdy(kServer, network_isolation_key1_, true);
  EXPECT_TRUE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
  EXPECT_TRUE(
      properties.SupportsRequestPriority(kServer, network_isolation_key1_));
  EXPECT_FALSE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
  EXPECT_FALSE(
      properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));

  properties.SetSupportsSpdy(kServer, NetworkIsolationKey(), true);
  EXPECT_TRUE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
  EXPECT_TRUE(
      properties.SupportsRequestPriority(kServer, network_isolation_key1_));
  EXPECT_TRUE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
  EXPECT_TRUE(
      properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));

  properties.SetSupportsSpdy(kServer, network_isolation_key1_, false);
  EXPECT_FALSE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
  EXPECT_FALSE(
      properties.SupportsRequestPriority(kServer, network_isolation_key1_));
  EXPECT_TRUE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
  EXPECT_TRUE(
      properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));

  properties.SetSupportsSpdy(kServer, NetworkIsolationKey(), false);
  EXPECT_FALSE(properties.GetSupportsSpdy(kServer, network_isolation_key1_));
  EXPECT_FALSE(
      properties.SupportsRequestPriority(kServer, network_isolation_key1_));
  EXPECT_FALSE(properties.GetSupportsSpdy(kServer, NetworkIsolationKey()));
  EXPECT_FALSE(
      properties.SupportsRequestPriority(kServer, NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, LoadSupportsSpdy) {
  HttpServerProperties::ServerInfo supports_spdy;
  supports_spdy.supports_spdy = true;
  HttpServerProperties::ServerInfo no_spdy;
  no_spdy.supports_spdy = false;

  url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
  url::SchemeHostPort spdy_server_photos("https", "photos.google.com", 443);
  url::SchemeHostPort spdy_server_docs("https", "docs.google.com", 443);
  url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);

  // Check by initializing empty spdy servers.
  std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers));
  EXPECT_FALSE(
      impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));

  // Check by initializing www.google.com:443 and photos.google.com:443 as spdy
  // servers.
  std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers1 =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  spdy_servers1->Put(CreateSimpleKey(spdy_server_google), supports_spdy);
  spdy_servers1->Put(CreateSimpleKey(spdy_server_photos), no_spdy);
  impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers1));
  // Note: these calls affect MRU order.
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.GetSupportsSpdy(spdy_server_photos, NetworkIsolationKey()));

  // Verify google and photos are in the list in MRU order.
  ASSERT_EQ(2U, impl_.server_info_map_for_testing().size());
  auto it = impl_.server_info_map_for_testing().begin();
  EXPECT_EQ(spdy_server_photos, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_FALSE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_google, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);

  // Check by initializing mail.google.com:443 and docs.google.com:443.
  std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers2 =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  spdy_servers2->Put(CreateSimpleKey(spdy_server_mail), supports_spdy);
  spdy_servers2->Put(CreateSimpleKey(spdy_server_docs), supports_spdy);
  impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers2));

  // Verify all the servers are in the list in MRU order. Note that
  // OnServerInfoLoadedForTesting will put existing spdy server entries in
  // front of newly added entries.
  ASSERT_EQ(4U, impl_.server_info_map_for_testing().size());
  it = impl_.server_info_map_for_testing().begin();
  EXPECT_EQ(spdy_server_photos, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_FALSE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_google, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_docs, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_mail, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);

  // Check these in reverse MRU order so that MRU order stays the same.
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_docs, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.GetSupportsSpdy(spdy_server_photos, NetworkIsolationKey()));

  // Verify that old values loaded from disk take precedence over newer learned
  // values and also verify the recency list order is unchanged.
  std::unique_ptr<HttpServerProperties::ServerInfoMap> spdy_servers3 =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  spdy_servers3->Put(CreateSimpleKey(spdy_server_mail), no_spdy);
  spdy_servers3->Put(CreateSimpleKey(spdy_server_photos), supports_spdy);
  impl_.OnServerInfoLoadedForTesting(std::move(spdy_servers3));

  // Verify the entries are in the same order.
  ASSERT_EQ(4U, impl_.server_info_map_for_testing().size());
  it = impl_.server_info_map_for_testing().begin();
  EXPECT_EQ(spdy_server_photos, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_google, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_docs, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_TRUE(*it->second.supports_spdy);
  ++it;
  EXPECT_EQ(spdy_server_mail, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.supports_spdy.has_value());
  EXPECT_FALSE(*it->second.supports_spdy);

  // Verify photos server doesn't support SPDY and other servers support SPDY.
  EXPECT_FALSE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_docs, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_photos, NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, SupportsRequestPriority) {
  url::SchemeHostPort spdy_server_empty("https", std::string(), 443);
  EXPECT_FALSE(
      impl_.SupportsRequestPriority(spdy_server_empty, NetworkIsolationKey()));

  // Add www.google.com:443 as supporting SPDY.
  url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
  impl_.SetSupportsSpdy(spdy_server_google, NetworkIsolationKey(), true);
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(spdy_server_google, NetworkIsolationKey()));

  // Add mail.google.com:443 as not supporting SPDY.
  url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);
  EXPECT_FALSE(
      impl_.SupportsRequestPriority(spdy_server_mail, NetworkIsolationKey()));

  // Add docs.google.com:443 as supporting SPDY.
  url::SchemeHostPort spdy_server_docs("https", "docs.google.com", 443);
  impl_.SetSupportsSpdy(spdy_server_docs, NetworkIsolationKey(), true);
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(spdy_server_docs, NetworkIsolationKey()));

  // Add www.youtube.com:443 as supporting QUIC.
  url::SchemeHostPort youtube_server("https", "www.youtube.com", 443);
  const AlternativeService alternative_service1(kProtoQUIC, "www.youtube.com",
                                                443);
  SetAlternativeService(youtube_server, alternative_service1);
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(youtube_server, NetworkIsolationKey()));

  // Add www.example.com:443 with two alternative services, one supporting QUIC.
  url::SchemeHostPort example_server("https", "www.example.com", 443);
  const AlternativeService alternative_service2(kProtoHTTP2, "", 443);
  SetAlternativeService(example_server, alternative_service2);
  SetAlternativeService(example_server, alternative_service1);
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(example_server, NetworkIsolationKey()));

  // Verify all the entries are the same after additions.
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(spdy_server_google, NetworkIsolationKey()));
  EXPECT_FALSE(
      impl_.SupportsRequestPriority(spdy_server_mail, NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(spdy_server_docs, NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(youtube_server, NetworkIsolationKey()));
  EXPECT_TRUE(
      impl_.SupportsRequestPriority(example_server, NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, ClearSupportsSpdy) {
  // Add www.google.com:443 and mail.google.com:443 as supporting SPDY.
  url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
  impl_.SetSupportsSpdy(spdy_server_google, NetworkIsolationKey(), true);
  url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);
  impl_.SetSupportsSpdy(spdy_server_mail, NetworkIsolationKey(), true);

  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));

  base::RunLoop run_loop;
  bool callback_invoked_ = false;
  impl_.Clear(base::BindOnce(
      [](bool* callback_invoked, base::OnceClosure quit_closure) {
        *callback_invoked = true;
        std::move(quit_closure).Run();
      },
      &callback_invoked_, run_loop.QuitClosure()));
  EXPECT_FALSE(
      impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetSupportsSpdy(spdy_server_mail, NetworkIsolationKey()));

  // Callback should be run asynchronously.
  EXPECT_FALSE(callback_invoked_);
  run_loop.Run();
  EXPECT_TRUE(callback_invoked_);
}

TEST_F(HttpServerPropertiesTest, MRUOfServerInfoMap) {
  url::SchemeHostPort spdy_server_google("https", "www.google.com", 443);
  url::SchemeHostPort spdy_server_mail("https", "mail.google.com", 443);

  // Add www.google.com:443 as supporting SPDY.
  impl_.SetSupportsSpdy(spdy_server_google, NetworkIsolationKey(), true);
  ASSERT_EQ(1u, impl_.server_info_map_for_testing().size());
  auto it = impl_.server_info_map_for_testing().begin();
  ASSERT_EQ(spdy_server_google, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());

  // Add mail.google.com:443 as supporting SPDY. Verify mail.google.com:443 and
  // www.google.com:443 are in the list.
  impl_.SetSupportsSpdy(spdy_server_mail, NetworkIsolationKey(), true);
  ASSERT_EQ(2u, impl_.server_info_map_for_testing().size());
  it = impl_.server_info_map_for_testing().begin();
  ASSERT_EQ(spdy_server_mail, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ++it;
  ASSERT_EQ(spdy_server_google, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());

  // Get www.google.com:443. It should become the most-recently-used server.
  EXPECT_TRUE(impl_.GetSupportsSpdy(spdy_server_google, NetworkIsolationKey()));
  ASSERT_EQ(2u, impl_.server_info_map_for_testing().size());
  it = impl_.server_info_map_for_testing().begin();
  ASSERT_EQ(spdy_server_google, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ++it;
  ASSERT_EQ(spdy_server_mail, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
}

typedef HttpServerPropertiesTest AlternateProtocolServerPropertiesTest;

TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
  url::SchemeHostPort test_server("http", "foo", 80);
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));

  AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  SetAlternativeService(test_server, alternative_service);
  const AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service,
            alternative_service_info_vector[0].alternative_service());

  impl_.Clear(base::OnceClosure());
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) {
  AlternativeServiceInfoVector alternative_service_info_vector;
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  // Same hostname, same port, TCP: should be ignored.
  AlternativeServiceInfo alternative_service_info1 =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          AlternativeService(kProtoHTTP2, "foo", 443), expiration);
  alternative_service_info_vector.push_back(alternative_service_info1);
  // Different hostname: GetAlternativeServiceInfos should return this one.
  AlternativeServiceInfo alternative_service_info2 =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          AlternativeService(kProtoHTTP2, "bar", 443), expiration);
  alternative_service_info_vector.push_back(alternative_service_info2);
  // Different port: GetAlternativeServiceInfos should return this one too.
  AlternativeServiceInfo alternative_service_info3 =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          AlternativeService(kProtoHTTP2, "foo", 80), expiration);
  alternative_service_info_vector.push_back(alternative_service_info3);
  // QUIC: GetAlternativeServices should return this one too.
  AlternativeServiceInfo alternative_service_info4 =
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          AlternativeService(kProtoQUIC, "foo", 443), expiration,
          DefaultSupportedQuicVersions());
  alternative_service_info_vector.push_back(alternative_service_info4);

  url::SchemeHostPort test_server("https", "foo", 443);
  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               alternative_service_info_vector);

  const AlternativeServiceInfoVector alternative_service_info_vector2 =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(3u, alternative_service_info_vector2.size());
  EXPECT_EQ(alternative_service_info2, alternative_service_info_vector2[0]);
  EXPECT_EQ(alternative_service_info3, alternative_service_info_vector2[1]);
  EXPECT_EQ(alternative_service_info4, alternative_service_info_vector2[2]);
}

TEST_F(AlternateProtocolServerPropertiesTest, Set) {
  // |test_server1| has an alternative service, which will not be
  // affected by OnServerInfoLoadedForTesting(), because
  // |server_info_map| does not have an entry for
  // |test_server1|.
  url::SchemeHostPort test_server1("http", "foo1", 80);
  const AlternativeService alternative_service1(kProtoHTTP2, "bar1", 443);
  const base::Time now = test_clock_.Now();
  base::Time expiration1 = now + base::TimeDelta::FromDays(1);
  // 1st entry in the memory.
  impl_.SetHttp2AlternativeService(test_server1, NetworkIsolationKey(),
                                   alternative_service1, expiration1);

  // |test_server2| has an alternative service, which will be
  // overwritten by OnServerInfoLoadedForTesting(), because
  // |server_info_map| has an entry for |test_server2|.
  AlternativeServiceInfoVector alternative_service_info_vector;
  const AlternativeService alternative_service2(kProtoHTTP2, "bar2", 443);
  base::Time expiration2 = now + base::TimeDelta::FromDays(2);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, expiration2));
  url::SchemeHostPort test_server2("http", "foo2", 80);
  // 0th entry in the memory.
  impl_.SetAlternativeServices(test_server2, NetworkIsolationKey(),
                               alternative_service_info_vector);

  // Prepare |server_info_map| to be loaded by OnServerInfoLoadedForTesting().
  std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  const AlternativeService alternative_service3(kProtoHTTP2, "bar3", 123);
  base::Time expiration3 = now + base::TimeDelta::FromDays(3);
  const AlternativeServiceInfo alternative_service_info1 =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service3, expiration3);
  // Simulate updating data for 0th entry with data from Preferences.
  server_info_map->GetOrPut(CreateSimpleKey(test_server2))
      ->second.alternative_services =
      AlternativeServiceInfoVector(/*size=*/1, alternative_service_info1);

  url::SchemeHostPort test_server3("http", "foo3", 80);
  const AlternativeService alternative_service4(kProtoHTTP2, "bar4", 1234);
  base::Time expiration4 = now + base::TimeDelta::FromDays(4);
  const AlternativeServiceInfo alternative_service_info2 =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service4, expiration4);
  // Add an old entry from Preferences, this will be added to end of recency
  // list.
  server_info_map->GetOrPut(CreateSimpleKey(test_server3))
      ->second.alternative_services =
      AlternativeServiceInfoVector(/*size=*/1, alternative_service_info2);

  // MRU list will be test_server2, test_server1, test_server3.
  impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));

  // Verify server_info_map.
  const HttpServerProperties::ServerInfoMap& map =
      impl_.server_info_map_for_testing();
  ASSERT_EQ(3u, map.size());
  auto map_it = map.begin();

  EXPECT_EQ(test_server2, map_it->first.server);
  EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(map_it->second.alternative_services.has_value());
  const AlternativeServiceInfoVector* service_info =
      &map_it->second.alternative_services.value();
  ASSERT_EQ(1u, service_info->size());
  EXPECT_EQ(alternative_service3, (*service_info)[0].alternative_service());
  EXPECT_EQ(expiration3, (*service_info)[0].expiration());

  ++map_it;
  EXPECT_EQ(test_server1, map_it->first.server);
  EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(map_it->second.alternative_services.has_value());
  service_info = &map_it->second.alternative_services.value();
  ASSERT_EQ(1u, service_info->size());
  EXPECT_EQ(alternative_service1, (*service_info)[0].alternative_service());
  EXPECT_EQ(expiration1, (*service_info)[0].expiration());

  ++map_it;
  EXPECT_EQ(map_it->first.server, test_server3);
  EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(map_it->second.alternative_services.has_value());
  service_info = &map_it->second.alternative_services.value();
  ASSERT_EQ(1u, service_info->size());
  EXPECT_EQ(alternative_service4, (*service_info)[0].alternative_service());
  EXPECT_EQ(expiration4, (*service_info)[0].expiration());
}

TEST_F(AlternateProtocolServerPropertiesTest, SetWebSockets) {
  // The https and wss servers should be treated as the same server, as should
  // the http and ws servers.
  url::SchemeHostPort https_server("https", "www.test.com", 443);
  url::SchemeHostPort wss_server("wss", "www.test.com", 443);
  url::SchemeHostPort http_server("http", "www.test.com", 443);
  url::SchemeHostPort ws_server("ws", "www.test.com", 443);

  AlternativeService alternative_service(kProtoHTTP2, "bar", 443);

  EXPECT_EQ(
      0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
                .size());

  SetAlternativeService(wss_server, alternative_service);
  EXPECT_EQ(
      1u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
  EXPECT_EQ(1u,
            impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
                .size());

  SetAlternativeService(http_server, alternative_service);
  EXPECT_EQ(
      1u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
  EXPECT_EQ(1u,
            impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(1u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(1u,
            impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
                .size());

  impl_.SetAlternativeServices(https_server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());
  EXPECT_EQ(
      0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(1u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(1u,
            impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
                .size());

  impl_.SetAlternativeServices(ws_server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());
  EXPECT_EQ(
      0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(wss_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(ws_server, NetworkIsolationKey())
                .size());
}

TEST_F(AlternateProtocolServerPropertiesTest, SetWithNetworkIsolationKey) {
  const url::SchemeHostPort kServer("https", "foo.test", 443);
  const AlternativeServiceInfoVector kAlternativeServices(
      {AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          AlternativeService(kProtoHTTP2, "foo", 443),
          base::Time::Now() + base::TimeDelta::FromDays(1) /* expiration */)});

  EXPECT_TRUE(impl_.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
                  .empty());
  EXPECT_TRUE(
      impl_.GetAlternativeServiceInfos(kServer, NetworkIsolationKey()).empty());

  // Without network isolation keys enabled for HttpServerProperties, passing in
  // a NetworkIsolationKey should have no effect on behavior.
  for (const auto& network_isolation_key_to_set :
       {NetworkIsolationKey(), network_isolation_key1_}) {
    impl_.SetAlternativeServices(kServer, network_isolation_key_to_set,
                                 kAlternativeServices);
    EXPECT_EQ(kAlternativeServices, impl_.GetAlternativeServiceInfos(
                                        kServer, network_isolation_key1_));
    EXPECT_EQ(kAlternativeServices,
              impl_.GetAlternativeServiceInfos(kServer, NetworkIsolationKey()));

    impl_.SetAlternativeServices(kServer, network_isolation_key_to_set,
                                 AlternativeServiceInfoVector());
    EXPECT_TRUE(
        impl_.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
            .empty());
    EXPECT_TRUE(impl_.GetAlternativeServiceInfos(kServer, NetworkIsolationKey())
                    .empty());
  }

  // Check that with network isolation keys enabled for HttpServerProperties,
  // the NetworkIsolationKey argument is respected.

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  properties.SetAlternativeServices(kServer, network_isolation_key1_,
                                    kAlternativeServices);
  EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
                                      kServer, network_isolation_key1_));
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(kServer, NetworkIsolationKey())
          .empty());

  properties.SetAlternativeServices(kServer, NetworkIsolationKey(),
                                    kAlternativeServices);
  EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
                                      kServer, network_isolation_key1_));
  EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
                                      kServer, NetworkIsolationKey()));

  properties.SetAlternativeServices(kServer, network_isolation_key1_,
                                    AlternativeServiceInfoVector());
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
          .empty());
  EXPECT_EQ(kAlternativeServices, properties.GetAlternativeServiceInfos(
                                      kServer, NetworkIsolationKey()));

  properties.SetAlternativeServices(kServer, NetworkIsolationKey(),
                                    AlternativeServiceInfoVector());
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(kServer, network_isolation_key1_)
          .empty());
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(kServer, NetworkIsolationKey())
          .empty());
}

// Regression test for https://crbug.com/504032:
// OnServerInfoLoadedForTesting() should not crash if there is an
// empty hostname is the mapping.
TEST_F(AlternateProtocolServerPropertiesTest, SetWithEmptyHostname) {
  url::SchemeHostPort server("https", "foo", 443);
  const AlternativeService alternative_service_with_empty_hostname(kProtoHTTP2,
                                                                   "", 1234);
  const AlternativeService alternative_service_with_foo_hostname(kProtoHTTP2,
                                                                 "foo", 1234);
  SetAlternativeService(server, alternative_service_with_empty_hostname);
  impl_.MarkAlternativeServiceBroken(alternative_service_with_foo_hostname,
                                     NetworkIsolationKey());

  std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));

  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(
      alternative_service_with_foo_hostname, NetworkIsolationKey()));
  const AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service_with_foo_hostname,
            alternative_service_info_vector[0].alternative_service());
}

// Regression test for https://crbug.com/516486:
// GetAlternativeServiceInfos() should remove |server_info_map_|
// elements with empty value.
TEST_F(AlternateProtocolServerPropertiesTest, EmptyVector) {
  url::SchemeHostPort server("https", "foo", 443);
  const AlternativeService alternative_service(kProtoHTTP2, "bar", 443);
  base::Time expiration = test_clock_.Now() - base::TimeDelta::FromDays(1);
  const AlternativeServiceInfo alternative_service_info =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service, expiration);
  std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  server_info_map->GetOrPut(CreateSimpleKey(server))
      ->second.alternative_services = AlternativeServiceInfoVector(
      /*size=*/1, alternative_service_info);

  // Prepare |server_info_map_| with a single key that has a single
  // AlternativeServiceInfo with identical hostname and port.
  impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));

  // GetAlternativeServiceInfos() should remove such AlternativeServiceInfo from
  // |server_info_map_|, emptying the AlternativeServiceInfoVector
  // corresponding to |server|.
  ASSERT_TRUE(
      impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());

  // GetAlternativeServiceInfos() should remove this key from
  // |server_info_map_|, and SetAlternativeServices() should not crash.
  impl_.SetAlternativeServices(
      server, NetworkIsolationKey(),
      AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));

  // There should still be no alternative service assigned to |server|.
  ASSERT_TRUE(
      impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());
}

// Regression test for https://crbug.com/516486 for the canonical host case.
TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) {
  url::SchemeHostPort server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  const AlternativeService alternative_service(kProtoHTTP2, "", 443);
  base::Time expiration = test_clock_.Now() - base::TimeDelta::FromDays(1);
  const AlternativeServiceInfo alternative_service_info =
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service, expiration);
  std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  server_info_map->GetOrPut(CreateSimpleKey(canonical_server))
      ->second.alternative_services =
      AlternativeServiceInfoVector(/*size=*/1, alternative_service_info);

  // Prepare |server_info_map_| with a single key that has a single
  // AlternativeServiceInfo with identical hostname and port.
  impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));

  // GetAlternativeServiceInfos() should remove such AlternativeServiceInfo from
  // |server_info_map_|, emptying the AlternativeServiceInfoVector
  // corresponding to |canonical_server|, even when looking up
  // alternative services for |server|.
  ASSERT_TRUE(
      impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());

  // GetAlternativeServiceInfos() should remove this key from
  // |server_info_map_|, and SetAlternativeServices() should not crash.
  impl_.SetAlternativeServices(
      canonical_server, NetworkIsolationKey(),
      AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));

  // There should still be no alternative service assigned to
  // |canonical_server|.
  ASSERT_TRUE(
      impl_.GetAlternativeServiceInfos(canonical_server, NetworkIsolationKey())
          .empty());
}

TEST_F(AlternateProtocolServerPropertiesTest, ClearServerWithCanonical) {
  url::SchemeHostPort server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  const AlternativeService alternative_service(kProtoQUIC, "", 443);
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  const AlternativeServiceInfo alternative_service_info =
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          alternative_service, expiration, DefaultSupportedQuicVersions());

  impl_.SetAlternativeServices(
      canonical_server, NetworkIsolationKey(),
      AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));

  // Make sure the canonical service is returned for the other server.
  const AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(kProtoQUIC,
            alternative_service_info_vector[0].alternative_service().protocol);
  EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);

  // Now clear the alternatives for the other server and make sure it stays
  // cleared.
  // GetAlternativeServices() should remove this key from
  // |server_info_map_|, and SetAlternativeServices() should not crash.
  impl_.SetAlternativeServices(server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());

  ASSERT_TRUE(
      impl_.GetAlternativeServiceInfos(server, NetworkIsolationKey()).empty());
}

TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServiceInfos) {
  url::SchemeHostPort test_server1("http", "foo1", 80);
  const AlternativeService alternative_service1(kProtoHTTP2, "foo1", 443);
  SetAlternativeService(test_server1, alternative_service1);
  url::SchemeHostPort test_server2("http", "foo2", 80);
  const AlternativeService alternative_service2(kProtoHTTP2, "foo2", 1234);
  SetAlternativeService(test_server2, alternative_service2);

  const HttpServerProperties::ServerInfoMap& map =
      impl_.server_info_map_for_testing();
  auto it = map.begin();
  EXPECT_EQ(test_server2, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.alternative_services.has_value());
  ASSERT_EQ(1u, it->second.alternative_services->size());
  EXPECT_EQ(alternative_service2,
            it->second.alternative_services.value()[0].alternative_service());

  const AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server1, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());

  // GetAlternativeServices should reorder the AlternateProtocol map.
  it = map.begin();
  EXPECT_EQ(test_server1, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.alternative_services.has_value());
  ASSERT_EQ(1u, it->second.alternative_services->size());
  EXPECT_EQ(alternative_service1,
            it->second.alternative_services.value()[0].alternative_service());
}

TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
  url::SchemeHostPort test_server("http", "foo", 80);
  const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
  SetAlternativeService(test_server, alternative_service1);
  AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                                NetworkIsolationKey()));

  // GetAlternativeServiceInfos should return the broken alternative service.
  impl_.MarkAlternativeServiceBroken(alternative_service1,
                                     NetworkIsolationKey());
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));

  // SetAlternativeServices should add a broken alternative service to the map.
  AlternativeServiceInfoVector alternative_service_info_vector2;
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  alternative_service_info_vector2.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service1, expiration));
  const AlternativeService alternative_service2(kProtoHTTP2, "foo", 1234);
  alternative_service_info_vector2.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, expiration));
  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               alternative_service_info_vector2);
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(2u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_EQ(alternative_service2,
            alternative_service_info_vector[1].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
                                                NetworkIsolationKey()));

  // SetAlternativeService should add a broken alternative service to the map.
  SetAlternativeService(test_server, alternative_service1);
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       SetBrokenUntilDefaultNetworkChanges) {
  url::SchemeHostPort test_server("http", "foo", 80);
  const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
  SetAlternativeService(test_server, alternative_service1);
  AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                                NetworkIsolationKey()));

  // Mark the alternative service as broken until the default network changes.
  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service1, NetworkIsolationKey());
  // The alternative service should be persisted and marked as broken.
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));

  // SetAlternativeServices should add a broken alternative service to the map.
  AlternativeServiceInfoVector alternative_service_info_vector2;
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  alternative_service_info_vector2.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service1, expiration));
  const AlternativeService alternative_service2(kProtoHTTP2, "foo", 1234);
  alternative_service_info_vector2.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, expiration));
  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               alternative_service_info_vector2);
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(2u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_EQ(alternative_service2,
            alternative_service_info_vector[1].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
                                                NetworkIsolationKey()));

  // SetAlternativeService should add a broken alternative service to the map.
  SetAlternativeService(test_server, alternative_service1);
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service1,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest, MaxAge) {
  AlternativeServiceInfoVector alternative_service_info_vector;
  base::Time now = test_clock_.Now();
  base::TimeDelta one_day = base::TimeDelta::FromDays(1);

  // First alternative service expired one day ago, should not be returned by
  // GetAlternativeServiceInfos().
  const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service1, now - one_day));

  // Second alterrnative service will expire one day from now, should be
  // returned by GetAlternativeSerices().
  const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, now + one_day));

  url::SchemeHostPort test_server("http", "foo", 80);
  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               alternative_service_info_vector);

  AlternativeServiceInfoVector alternative_service_info_vector2 =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector2.size());
  EXPECT_EQ(alternative_service2,
            alternative_service_info_vector2[0].alternative_service());
}

TEST_F(AlternateProtocolServerPropertiesTest, MaxAgeCanonical) {
  AlternativeServiceInfoVector alternative_service_info_vector;
  base::Time now = test_clock_.Now();
  base::TimeDelta one_day = base::TimeDelta::FromDays(1);

  // First alternative service expired one day ago, should not be returned by
  // GetAlternativeServiceInfos().
  const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service1, now - one_day));

  // Second alterrnative service will expire one day from now, should be
  // returned by GetAlternativeSerices().
  const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, now + one_day));

  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  impl_.SetAlternativeServices(canonical_server, NetworkIsolationKey(),
                               alternative_service_info_vector);

  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  AlternativeServiceInfoVector alternative_service_info_vector2 =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector2.size());
  EXPECT_EQ(alternative_service2,
            alternative_service_info_vector2[0].alternative_service());
}

TEST_F(AlternateProtocolServerPropertiesTest, AlternativeServiceWithScheme) {
  AlternativeServiceInfoVector alternative_service_info_vector;
  const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service1, expiration));
  const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, expiration));
  // Set Alt-Svc list for |http_server|.
  url::SchemeHostPort http_server("http", "foo", 80);
  impl_.SetAlternativeServices(http_server, NetworkIsolationKey(),
                               alternative_service_info_vector);

  const net::HttpServerProperties::ServerInfoMap& map =
      impl_.server_info_map_for_testing();
  auto it = map.begin();
  EXPECT_EQ(http_server, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.alternative_services.has_value());
  ASSERT_EQ(2u, it->second.alternative_services->size());
  EXPECT_EQ(alternative_service1,
            it->second.alternative_services.value()[0].alternative_service());
  EXPECT_EQ(alternative_service2,
            it->second.alternative_services.value()[1].alternative_service());

  // Check Alt-Svc list should not be set for |https_server|.
  url::SchemeHostPort https_server("https", "foo", 80);
  EXPECT_EQ(
      0u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());

  // Set Alt-Svc list for |https_server|.
  impl_.SetAlternativeServices(https_server, NetworkIsolationKey(),
                               alternative_service_info_vector);
  EXPECT_EQ(
      2u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
  EXPECT_EQ(2u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());

  // Clear Alt-Svc list for |http_server|.
  impl_.SetAlternativeServices(http_server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());

  EXPECT_EQ(0u,
            impl_.GetAlternativeServiceInfos(http_server, NetworkIsolationKey())
                .size());
  EXPECT_EQ(
      2u, impl_.GetAlternativeServiceInfos(https_server, NetworkIsolationKey())
              .size());
}

TEST_F(AlternateProtocolServerPropertiesTest, ClearAlternativeServices) {
  AlternativeServiceInfoVector alternative_service_info_vector;
  const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443);
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service1, expiration));
  const AlternativeService alternative_service2(kProtoHTTP2, "bar", 1234);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          alternative_service2, expiration));
  url::SchemeHostPort test_server("http", "foo", 80);
  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               alternative_service_info_vector);

  const net::HttpServerProperties::ServerInfoMap& map =
      impl_.server_info_map_for_testing();
  auto it = map.begin();
  EXPECT_EQ(test_server, it->first.server);
  EXPECT_TRUE(it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(it->second.alternative_services.has_value());
  ASSERT_EQ(2u, it->second.alternative_services->size());
  EXPECT_EQ(alternative_service1,
            it->second.alternative_services.value()[0].alternative_service());
  EXPECT_EQ(alternative_service2,
            it->second.alternative_services.value()[1].alternative_service());

  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());
  EXPECT_TRUE(map.empty());
}

// A broken alternative service in the mapping carries meaningful information,
// therefore it should not be ignored by SetAlternativeService().  In
// particular, an alternative service mapped to an origin shadows alternative
// services of canonical hosts.
TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) {
  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  AlternativeService canonical_alternative_service(kProtoQUIC,
                                                   "bar.c.youtube.com", 1234);
  SetAlternativeService(canonical_server, canonical_alternative_service);
  AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(canonical_alternative_service,
            alternative_service_info_vector[0].alternative_service());

  const AlternativeService broken_alternative_service(kProtoHTTP2, "foo", 443);
  impl_.MarkAlternativeServiceBroken(broken_alternative_service,
                                     NetworkIsolationKey());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service,
                                               NetworkIsolationKey()));

  SetAlternativeService(test_server, broken_alternative_service);
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(broken_alternative_service,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service,
                                               NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) {
  url::SchemeHostPort test_server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  SetAlternativeService(test_server, alternative_service);
  impl_.MarkAlternativeServiceBroken(alternative_service,
                                     NetworkIsolationKey());
  ASSERT_TRUE(HasAlternativeService(test_server, NetworkIsolationKey()));
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  // SetAlternativeServices should leave a broken alternative service marked
  // as such.
  impl_.SetAlternativeServices(test_server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       MarkBrokenWithNetworkIsolationKey) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  const base::Time expiration =
      test_clock_.Now() + base::TimeDelta::FromDays(1);

  // Without NetworkIsolationKeys enabled, the NetworkIsolationKey parameter
  // should be ignored.
  impl_.SetHttp2AlternativeService(server, network_isolation_key1_,
                                   alternative_service, expiration);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  impl_.MarkAlternativeServiceBroken(alternative_service,
                                     network_isolation_key1_);
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               network_isolation_key1_));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               network_isolation_key2_));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  impl_.ConfirmAlternativeService(alternative_service, network_isolation_key2_);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  properties.SetHttp2AlternativeService(server, network_isolation_key1_,
                                        alternative_service, expiration);
  properties.SetHttp2AlternativeService(server, network_isolation_key2_,
                                        alternative_service, expiration);

  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceBroken(alternative_service,
                                          network_isolation_key1_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceBroken(alternative_service,
                                          network_isolation_key2_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.ConfirmAlternativeService(alternative_service,
                                       network_isolation_key1_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.ConfirmAlternativeService(alternative_service,
                                       network_isolation_key2_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));
}

TEST_F(AlternateProtocolServerPropertiesTest, MarkRecentlyBroken) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  SetAlternativeService(server, alternative_service);

  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));

  impl_.MarkAlternativeServiceRecentlyBroken(alternative_service,
                                             NetworkIsolationKey());
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  impl_.ConfirmAlternativeService(alternative_service, NetworkIsolationKey());
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       MarkRecentlyBrokenWithNetworkIsolationKey) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  const base::Time expiration =
      test_clock_.Now() + base::TimeDelta::FromDays(1);

  // Without NetworkIsolationKeys enabled, the NetworkIsolationKey parameter
  // should be ignored.
  impl_.SetHttp2AlternativeService(server, network_isolation_key1_,
                                   alternative_service, expiration);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  impl_.MarkAlternativeServiceRecentlyBroken(alternative_service,
                                             network_isolation_key1_);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  impl_.ConfirmAlternativeService(alternative_service, network_isolation_key2_);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  properties.SetHttp2AlternativeService(server, network_isolation_key1_,
                                        alternative_service, expiration);
  properties.SetHttp2AlternativeService(server, network_isolation_key2_,
                                        alternative_service, expiration);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceRecentlyBroken(alternative_service,
                                                  network_isolation_key1_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceRecentlyBroken(alternative_service,
                                                  network_isolation_key2_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.ConfirmAlternativeService(alternative_service,
                                       network_isolation_key1_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.ConfirmAlternativeService(alternative_service,
                                       network_isolation_key2_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       MarkBrokenUntilDefaultNetworkChanges) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  SetAlternativeService(server, alternative_service);

  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));

  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, NetworkIsolationKey());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  impl_.ConfirmAlternativeService(alternative_service, NetworkIsolationKey());
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       MarkBrokenUntilDefaultNetworkChangesWithNetworkIsolationKey) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);
  const base::Time expiration =
      test_clock_.Now() + base::TimeDelta::FromDays(1);

  // Without NetworkIsolationKeys enabled, the NetworkIsolationKey parameter
  // should be ignored.
  impl_.SetHttp2AlternativeService(server, network_isolation_key1_,
                                   alternative_service, expiration);

  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, network_isolation_key1_);
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               network_isolation_key1_));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               network_isolation_key2_));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  impl_.ConfirmAlternativeService(alternative_service, network_isolation_key2_);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key1_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                network_isolation_key2_));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  properties.SetHttp2AlternativeService(server, network_isolation_key1_,
                                        alternative_service, expiration);
  properties.SetHttp2AlternativeService(server, network_isolation_key2_,
                                        alternative_service, expiration);

  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, network_isolation_key1_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, network_isolation_key2_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.ConfirmAlternativeService(alternative_service,
                                       network_isolation_key1_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.ConfirmAlternativeService(alternative_service,
                                       network_isolation_key2_);
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));
}

TEST_F(AlternateProtocolServerPropertiesTest, OnDefaultNetworkChanged) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);

  SetAlternativeService(server, alternative_service);
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));

  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, NetworkIsolationKey());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  // Default network change clears alt svc broken until default network changes.
  impl_.OnDefaultNetworkChanged();
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));

  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, NetworkIsolationKey());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  impl_.MarkAlternativeServiceBroken(alternative_service,
                                     NetworkIsolationKey());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  // Default network change doesn't affect alt svc that was simply marked broken
  // most recently.
  impl_.OnDefaultNetworkChanged();
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, NetworkIsolationKey());
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  // Default network change clears alt svc that was marked broken until default
  // network change most recently even if the alt svc was initially marked
  // broken.
  impl_.OnDefaultNetworkChanged();
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       OnDefaultNetworkChangedWithNetworkIsolationKey) {
  url::SchemeHostPort server("http", "foo", 80);
  const AlternativeService alternative_service(kProtoHTTP2, "foo", 443);

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  const base::Time expiration =
      test_clock_.Now() + base::TimeDelta::FromDays(1);
  properties.SetHttp2AlternativeService(server, network_isolation_key1_,
                                        alternative_service, expiration);
  properties.SetHttp2AlternativeService(server, network_isolation_key2_,
                                        alternative_service, expiration);

  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, network_isolation_key1_);
  properties.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      alternative_service, network_isolation_key2_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  // Default network change clears alt svc broken until default network changes.
  properties.OnDefaultNetworkChanged();
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));
}

TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));

  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  EXPECT_FALSE(HasAlternativeService(canonical_server, NetworkIsolationKey()));

  AlternativeServiceInfoVector alternative_service_info_vector;
  const AlternativeService canonical_alternative_service1(
      kProtoQUIC, "bar.c.youtube.com", 1234);
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          canonical_alternative_service1, expiration,
          DefaultSupportedQuicVersions()));
  const AlternativeService canonical_alternative_service2(kProtoHTTP2, "", 443);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          canonical_alternative_service2, expiration));
  impl_.SetAlternativeServices(canonical_server, NetworkIsolationKey(),
                               alternative_service_info_vector);

  // Since |test_server| does not have an alternative service itself,
  // GetAlternativeServiceInfos should return those of |canonical_server|.
  AlternativeServiceInfoVector alternative_service_info_vector2 =
      impl_.GetAlternativeServiceInfos(test_server, NetworkIsolationKey());
  ASSERT_EQ(2u, alternative_service_info_vector2.size());
  EXPECT_EQ(canonical_alternative_service1,
            alternative_service_info_vector2[0].alternative_service());

  // Since |canonical_alternative_service2| has an empty host,
  // GetAlternativeServiceInfos should substitute the hostname of its |origin|
  // argument.
  EXPECT_EQ(test_server.host(),
            alternative_service_info_vector2[1].alternative_service().host);
  EXPECT_EQ(canonical_alternative_service2.protocol,
            alternative_service_info_vector2[1].alternative_service().protocol);
  EXPECT_EQ(canonical_alternative_service2.port,
            alternative_service_info_vector2[1].alternative_service().port);

  // Verify the canonical suffix.
  EXPECT_EQ(".c.youtube.com",
            *impl_.GetCanonicalSuffixForTesting(test_server.host()));
  EXPECT_EQ(".c.youtube.com",
            *impl_.GetCanonicalSuffixForTesting(canonical_server.host()));
}

TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  AlternativeService canonical_alternative_service(kProtoQUIC,
                                                   "bar.c.youtube.com", 1234);

  SetAlternativeService(canonical_server, canonical_alternative_service);
  impl_.SetAlternativeServices(canonical_server, NetworkIsolationKey(),
                               AlternativeServiceInfoVector());
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       CanonicalWithNetworkIsolationKey) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  EXPECT_FALSE(HasAlternativeService(test_server, network_isolation_key1_));

  url::SchemeHostPort canonical_server1("https", "bar.c.youtube.com", 443);
  EXPECT_FALSE(
      HasAlternativeService(canonical_server1, network_isolation_key1_));

  AlternativeServiceInfoVector alternative_service_info_vector;
  const AlternativeService canonical_alternative_service1(
      kProtoQUIC, "bar.c.youtube.com", 1234);
  base::Time expiration = test_clock_.Now() + base::TimeDelta::FromDays(1);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          canonical_alternative_service1, expiration,
          DefaultSupportedQuicVersions()));
  const AlternativeService canonical_alternative_service2(kProtoHTTP2, "", 443);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          canonical_alternative_service2, expiration));
  properties.SetAlternativeServices(canonical_server1, network_isolation_key1_,
                                    alternative_service_info_vector);

  // Since |test_server| does not have an alternative service itself,
  // GetAlternativeServiceInfos should return those of |canonical_server|.
  AlternativeServiceInfoVector alternative_service_info_vector2 =
      properties.GetAlternativeServiceInfos(test_server,
                                            network_isolation_key1_);
  ASSERT_EQ(2u, alternative_service_info_vector2.size());
  EXPECT_EQ(canonical_alternative_service1,
            alternative_service_info_vector2[0].alternative_service());

  // Canonical information should not be visible for other NetworkIsolationKeys.
  EXPECT_TRUE(
      properties
          .GetAlternativeServiceInfos(test_server, network_isolation_key2_)
          .empty());
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
          .empty());

  // Now add an alternative service entry for network_isolation_key2_ for a
  // different server and different NetworkIsolationKey, but with the same
  // canonical suffix.
  url::SchemeHostPort canonical_server2("https", "shrimp.c.youtube.com", 443);
  properties.SetAlternativeServices(canonical_server2, network_isolation_key2_,
                                    {alternative_service_info_vector[0]});

  // The canonical server information should reachable, and different, for both
  // NetworkIsolationKeys.
  EXPECT_EQ(
      1u, properties
              .GetAlternativeServiceInfos(test_server, network_isolation_key2_)
              .size());
  EXPECT_EQ(
      2u, properties
              .GetAlternativeServiceInfos(test_server, network_isolation_key1_)
              .size());
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
          .empty());

  // Clearing the alternate service state of network_isolation_key1_'s canonical
  // server should only affect network_isolation_key1_.
  properties.SetAlternativeServices(canonical_server1, network_isolation_key1_,
                                    {});
  EXPECT_EQ(
      1u, properties
              .GetAlternativeServiceInfos(test_server, network_isolation_key2_)
              .size());
  EXPECT_TRUE(
      properties
          .GetAlternativeServiceInfos(test_server, network_isolation_key1_)
          .empty());
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
          .empty());
}

TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) {
  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  AlternativeService canonical_alternative_service(kProtoQUIC,
                                                   "bar.c.youtube.com", 1234);

  SetAlternativeService(canonical_server, canonical_alternative_service);
  EXPECT_TRUE(HasAlternativeService(test_server, NetworkIsolationKey()));
  impl_.MarkAlternativeServiceBroken(canonical_alternative_service,
                                     NetworkIsolationKey());
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       CanonicalBrokenUntilDefaultNetworkChanges) {
  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  AlternativeService canonical_alternative_service(kProtoQUIC,
                                                   "bar.c.youtube.com", 1234);

  SetAlternativeService(canonical_server, canonical_alternative_service);
  EXPECT_TRUE(HasAlternativeService(test_server, NetworkIsolationKey()));
  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      canonical_alternative_service, NetworkIsolationKey());
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
}

// Adding an alternative service for a new host overrides canonical host.
TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) {
  url::SchemeHostPort foo_server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort bar_server("https", "bar.c.youtube.com", 443);
  AlternativeService bar_alternative_service(kProtoQUIC, "bar.c.youtube.com",
                                             1234);
  SetAlternativeService(bar_server, bar_alternative_service);
  AlternativeServiceInfoVector alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(foo_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(bar_alternative_service,
            alternative_service_info_vector[0].alternative_service());

  url::SchemeHostPort qux_server("https", "qux.c.youtube.com", 443);
  AlternativeService qux_alternative_service(kProtoQUIC, "qux.c.youtube.com",
                                             443);
  SetAlternativeService(qux_server, qux_alternative_service);
  alternative_service_info_vector =
      impl_.GetAlternativeServiceInfos(foo_server, NetworkIsolationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(qux_alternative_service,
            alternative_service_info_vector[0].alternative_service());
}

TEST_F(AlternateProtocolServerPropertiesTest, ClearWithCanonical) {
  url::SchemeHostPort test_server("https", "foo.c.youtube.com", 443);
  url::SchemeHostPort canonical_server("https", "bar.c.youtube.com", 443);
  AlternativeService canonical_alternative_service(kProtoQUIC,
                                                   "bar.c.youtube.com", 1234);

  SetAlternativeService(canonical_server, canonical_alternative_service);
  impl_.Clear(base::OnceClosure());
  EXPECT_FALSE(HasAlternativeService(test_server, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       ExpireBrokenAlternateProtocolMappings) {
  url::SchemeHostPort server("https", "foo", 443);
  AlternativeService alternative_service(kProtoQUIC, "foo", 443);
  SetAlternativeService(server, alternative_service);
  EXPECT_TRUE(HasAlternativeService(server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      alternative_service, NetworkIsolationKey()));

  base::TimeTicks past =
      test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
  HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
      &impl_, alternative_service, past);
  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service,
                                               NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));

  HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&impl_);
  EXPECT_FALSE(HasAlternativeService(server, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service,
                                                NetworkIsolationKey()));
  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service,
                                                        NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       ExpireBrokenAlternateProtocolMappingsWithNetworkIsolationKey) {
  url::SchemeHostPort server("https", "foo", 443);
  AlternativeService alternative_service(kProtoHTTP2, "foo", 444);
  base::TimeTicks past =
      test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
  base::TimeTicks future =
      test_tick_clock_->NowTicks() + base::TimeDelta::FromSeconds(42);
  const base::Time alt_service_expiration =
      test_clock_.Now() + base::TimeDelta::FromDays(1);

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  properties.SetHttp2AlternativeService(server, network_isolation_key1_,
                                        alternative_service,
                                        alt_service_expiration);
  properties.SetHttp2AlternativeService(server, network_isolation_key2_,
                                        alternative_service,
                                        alt_service_expiration);

  EXPECT_FALSE(
      properties.GetAlternativeServiceInfos(server, network_isolation_key1_)
          .empty());
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(
      properties.GetAlternativeServiceInfos(server, network_isolation_key2_)
          .empty());
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  // Set broken alternative service with expiration date in the past for
  // |network_isolation_key1_|.
  HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
      &properties, alternative_service, past, network_isolation_key1_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key2_));
  EXPECT_FALSE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  // Set broken alternative service with expiration date in the future for
  // |network_isolation_key1_|.
  HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
      &properties, alternative_service, future, network_isolation_key2_);
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));

  // Only the broken entry for |network_isolation_key1_| should be expired.
  HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&properties);
  EXPECT_TRUE(
      properties.GetAlternativeServiceInfos(server, network_isolation_key1_)
          .empty());
  EXPECT_FALSE(properties.IsAlternativeServiceBroken(alternative_service,
                                                     network_isolation_key1_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key1_));
  EXPECT_FALSE(
      properties.GetAlternativeServiceInfos(server, network_isolation_key2_)
          .empty());
  EXPECT_TRUE(properties.IsAlternativeServiceBroken(alternative_service,
                                                    network_isolation_key2_));
  EXPECT_TRUE(properties.WasAlternativeServiceRecentlyBroken(
      alternative_service, network_isolation_key2_));
}

// Regression test for https://crbug.com/505413.
TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc) {
  url::SchemeHostPort foo_server("https", "foo", 443);
  AlternativeService bar_alternative_service(kProtoQUIC, "bar", 443);
  SetAlternativeService(foo_server, bar_alternative_service);
  EXPECT_TRUE(HasAlternativeService(foo_server, NetworkIsolationKey()));

  url::SchemeHostPort bar_server1("http", "bar", 80);
  AlternativeService nohost_alternative_service(kProtoQUIC, "", 443);
  SetAlternativeService(bar_server1, nohost_alternative_service);
  EXPECT_TRUE(HasAlternativeService(bar_server1, NetworkIsolationKey()));

  url::SchemeHostPort bar_server2("https", "bar", 443);
  AlternativeService baz_alternative_service(kProtoQUIC, "baz", 1234);
  SetAlternativeService(bar_server2, baz_alternative_service);
  EXPECT_TRUE(HasAlternativeService(bar_server2, NetworkIsolationKey()));

  // Mark "bar:443" as broken.
  base::TimeTicks past =
      test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
  HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
      &impl_, bar_alternative_service, past);

  // Expire brokenness of "bar:443".
  HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&impl_);

  // "foo:443" should have no alternative service now.
  EXPECT_FALSE(HasAlternativeService(foo_server, NetworkIsolationKey()));
  // "bar:80" should have no alternative service now.
  EXPECT_FALSE(HasAlternativeService(bar_server1, NetworkIsolationKey()));
  // The alternative service of "bar:443" should be unaffected.
  EXPECT_TRUE(HasAlternativeService(bar_server2, NetworkIsolationKey()));

  EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(bar_alternative_service,
                                                        NetworkIsolationKey()));
  EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(
      baz_alternative_service, NetworkIsolationKey()));
}

// Regression test for https://crbug.com/724302
TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc2) {
  // This test will mark an alternative service A that has already been marked
  // broken many times, then immediately mark another alternative service B as
  // broken for the first time. Because A's been marked broken many times
  // already, its brokenness will be scheduled to expire much further in the
  // future than B, even though it was marked broken before B. This test makes
  // sure that even though A was marked broken before B, B's brokenness should
  // expire before A.

  url::SchemeHostPort server1("https", "foo", 443);
  AlternativeService alternative_service1(kProtoQUIC, "foo", 443);
  SetAlternativeService(server1, alternative_service1);

  url::SchemeHostPort server2("https", "bar", 443);
  AlternativeService alternative_service2(kProtoQUIC, "bar", 443);
  SetAlternativeService(server2, alternative_service2);

  // Repeatedly mark alt svc 1 broken and wait for its brokenness to expire.
  // This will increase its time until expiration.
  for (int i = 0; i < 3; ++i) {
    impl_.MarkAlternativeServiceBroken(alternative_service1,
                                       NetworkIsolationKey());

    // |impl_| should have posted task to expire the brokenness of
    // |alternative_service1|
    EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
    EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                                 NetworkIsolationKey()));

    // Advance time by just enough so that |alternative_service1|'s brokenness
    // expires.
    FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[i]);

    // Ensure brokenness of |alternative_service1| has expired.
    EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
    EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                                  NetworkIsolationKey()));
  }

  impl_.MarkAlternativeServiceBroken(alternative_service1,
                                     NetworkIsolationKey());
  impl_.MarkAlternativeServiceBroken(alternative_service2,
                                     NetworkIsolationKey());

  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service2,
                                               NetworkIsolationKey()));

  // Advance time by just enough so that |alternative_service2|'s brokennness
  // expires.
  FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[0]);

  EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                               NetworkIsolationKey()));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
                                                NetworkIsolationKey()));

  // Advance time by enough so that |alternative_service1|'s brokenness expires.
  FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[3] -
                BROKEN_ALT_SVC_EXPIRE_DELAYS[0]);

  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service1,
                                                NetworkIsolationKey()));
  EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service2,
                                                NetworkIsolationKey()));
}

// Regression test for https://crbug.com/994537. Having a ServerInfo entry
// without a populated |alternative_services| value would cause
// OnExpireBrokenAlternativeService() to hang..
TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc3) {
  // Add an altertive service entry.
  const url::SchemeHostPort kServer1("https", "foo", 443);
  const AlternativeService kAltService(kProtoQUIC, "bar", 443);
  SetAlternativeService(kServer1, kAltService);
  EXPECT_TRUE(HasAlternativeService(kServer1, NetworkIsolationKey()));

  // Add an entry to ServerInfo for another server, without an alternative
  // service value.
  const url::SchemeHostPort kServer2("http", "bar", 80);
  impl_.SetSupportsSpdy(kServer2, NetworkIsolationKey(), false);

  // Mark kAltService as broken.
  base::TimeTicks past =
      test_tick_clock_->NowTicks() - base::TimeDelta::FromSeconds(42);
  HttpServerPropertiesPeer::AddBrokenAlternativeServiceWithExpirationTime(
      &impl_, kAltService, past);

  // Expire brokenness of kAltService. This call should not hang.
  HttpServerPropertiesPeer::ExpireBrokenAlternateProtocolMappings(&impl_);

  EXPECT_FALSE(HasAlternativeService(kServer1, NetworkIsolationKey()));
}

TEST_F(AlternateProtocolServerPropertiesTest,
       GetAlternativeServiceInfoAsValue) {
  base::Time::Exploded now_exploded;
  now_exploded.year = 2018;
  now_exploded.month = 1;
  now_exploded.day_of_week = 3;
  now_exploded.day_of_month = 24;
  now_exploded.hour = 15;
  now_exploded.minute = 12;
  now_exploded.second = 53;
  now_exploded.millisecond = 0;
  base::Time now;
  bool result = base::Time::FromLocalExploded(now_exploded, &now);
  DCHECK(result);
  test_clock_.SetNow(now);

  AlternativeServiceInfoVector alternative_service_info_vector;
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          AlternativeService(kProtoHTTP2, "foo", 443),
          now + base::TimeDelta::FromMinutes(1)));
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          AlternativeService(kProtoQUIC, "bar", 443),
          now + base::TimeDelta::FromHours(1), DefaultSupportedQuicVersions()));
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          AlternativeService(kProtoQUIC, "baz", 443),
          now + base::TimeDelta::FromHours(1), DefaultSupportedQuicVersions()));

  impl_.SetAlternativeServices(url::SchemeHostPort("https", "youtube.com", 443),
                               NetworkIsolationKey(),
                               alternative_service_info_vector);

  impl_.MarkAlternativeServiceBroken(AlternativeService(kProtoQUIC, "bar", 443),
                                     NetworkIsolationKey());

  impl_.MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
      AlternativeService(kProtoQUIC, "baz", 443), NetworkIsolationKey());

  alternative_service_info_vector.clear();
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
          AlternativeService(kProtoHTTP2, "foo2", 443),
          now + base::TimeDelta::FromDays(1)));
  impl_.SetAlternativeServices(url::SchemeHostPort("http", "test.com", 80),
                               NetworkIsolationKey(),
                               alternative_service_info_vector);

  const char expected_json[] =
      "["
      "{"
      "\"alternative_service\":"
      "[\"h2 foo2:443, expires 2018-01-25 15:12:53\"],"
      "\"network_isolation_key\":\"null null\","
      "\"server\":\"http://test.com\""
      "},"
      "{"
      "\"alternative_service\":"
      "[\"h2 foo:443, expires 2018-01-24 15:13:53\","
      "\"quic bar:443, expires 2018-01-24 16:12:53"
      " (broken until 2018-01-24 15:17:53)\","
      "\"quic baz:443, expires 2018-01-24 16:12:53"
      " (broken until 2018-01-24 15:17:53)\"],"
      "\"network_isolation_key\":\"null null\","
      "\"server\":\"https://youtube.com\""
      "}"
      "]";

  base::Value alternative_service_info_value =
      impl_.GetAlternativeServiceInfoAsValue();
  std::string alternative_service_info_json;
  base::JSONWriter::Write(alternative_service_info_value,
                          &alternative_service_info_json);
  EXPECT_EQ(expected_json, alternative_service_info_json);
}

TEST_F(HttpServerPropertiesTest, LoadLastLocalAddressWhenQuicWorked) {
  const IPAddress kEmptyAddress;
  const IPAddress kValidAddress1 = IPAddress::IPv4Localhost();
  const IPAddress kValidAddress2 = IPAddress::IPv6Localhost();

  // Check by initializing empty address.
  impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kEmptyAddress);
  EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
  // Empty address should not be considered an address that was used when QUIC
  // worked.
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // Check by initializing with a valid address.
  impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kValidAddress1);
  EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // Try another valid address.
  impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kValidAddress2);
  EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // And loading an empty address clears the current one.
  // TODO(mmenke): This seems like a bug, since if we've learned the current
  // network supports QUIC, surely we want to save that to disk? Seems like a
  // pre-existing value should take precedence, if non-empty, since if the
  // current network is already known to support QUIC, the loaded value is no
  // longer relevant.
  impl_.OnLastLocalAddressWhenQuicWorkedForTesting(kEmptyAddress);
  EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
}

TEST_F(HttpServerPropertiesTest, SetLastLocalAddressWhenQuicWorked) {
  const IPAddress kEmptyAddress;
  const IPAddress kValidAddress1 = IPAddress::IPv4Localhost();
  const IPAddress kValidAddress2 = IPAddress::IPv6Localhost();

  EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // Set to a valid address.
  impl_.SetLastLocalAddressWhenQuicWorked(kValidAddress1);
  EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // Clear only this value.
  impl_.ClearLastLocalAddressWhenQuicWorked();
  EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // Try another valid address.
  impl_.SetLastLocalAddressWhenQuicWorked(kValidAddress2);
  EXPECT_TRUE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_TRUE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));

  // Clear all values.
  impl_.Clear(base::OnceClosure());
  EXPECT_FALSE(impl_.HasLastLocalAddressWhenQuicWorked());
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kEmptyAddress));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress1));
  EXPECT_FALSE(impl_.WasLastLocalAddressWhenQuicWorked(kValidAddress2));
}

TEST_F(HttpServerPropertiesTest, LoadServerNetworkStats) {
  url::SchemeHostPort google_server("https", "www.google.com", 443);

  // Check by initializing empty ServerNetworkStats.
  std::unique_ptr<HttpServerProperties::ServerInfoMap> load_server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  impl_.OnServerInfoLoadedForTesting(std::move(load_server_info_map));
  const ServerNetworkStats* stats =
      impl_.GetServerNetworkStats(google_server, NetworkIsolationKey());
  EXPECT_EQ(nullptr, stats);

  // Check by initializing with www.google.com:443.
  ServerNetworkStats stats_google;
  stats_google.srtt = base::TimeDelta::FromMicroseconds(10);
  stats_google.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(100);
  load_server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();
  load_server_info_map->GetOrPut(CreateSimpleKey(google_server))
      ->second.server_network_stats = stats_google;
  impl_.OnServerInfoLoadedForTesting(std::move(load_server_info_map));

  // Verify data for www.google.com:443.
  ASSERT_EQ(1u, impl_.server_info_map_for_testing().size());
  EXPECT_EQ(stats_google, *(impl_.GetServerNetworkStats(
                              google_server, NetworkIsolationKey())));

  // Test recency order and overwriting of data.
  //
  // |docs_server| has a ServerNetworkStats, which will be overwritten by
  // OnServerInfoLoadedForTesting(), because |server_network_stats_map| has an
  // entry for |docs_server|.
  url::SchemeHostPort docs_server("https", "docs.google.com", 443);
  ServerNetworkStats stats_docs;
  stats_docs.srtt = base::TimeDelta::FromMicroseconds(20);
  stats_docs.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(200);
  // Recency order will be |docs_server| and |google_server|.
  impl_.SetServerNetworkStats(docs_server, NetworkIsolationKey(), stats_docs);

  // Prepare |server_info_map| to be loaded by OnServerInfoLoadedForTesting().
  std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map =
      std::make_unique<HttpServerProperties::ServerInfoMap>();

  // Change the values for |docs_server|.
  ServerNetworkStats new_stats_docs;
  new_stats_docs.srtt = base::TimeDelta::FromMicroseconds(25);
  new_stats_docs.bandwidth_estimate =
      quic::QuicBandwidth::FromBitsPerSecond(250);
  server_info_map->GetOrPut(CreateSimpleKey(docs_server))
      ->second.server_network_stats = new_stats_docs;
  // Add data for mail.google.com:443.
  url::SchemeHostPort mail_server("https", "mail.google.com", 443);
  ServerNetworkStats stats_mail;
  stats_mail.srtt = base::TimeDelta::FromMicroseconds(30);
  stats_mail.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(300);
  server_info_map->GetOrPut(CreateSimpleKey(mail_server))
      ->second.server_network_stats = stats_mail;

  // Recency order will be |docs_server|, |google_server| and |mail_server|.
  impl_.OnServerInfoLoadedForTesting(std::move(server_info_map));

  const HttpServerProperties::ServerInfoMap& map =
      impl_.server_info_map_for_testing();
  ASSERT_EQ(3u, map.size());
  auto map_it = map.begin();

  EXPECT_EQ(docs_server, map_it->first.server);
  EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(map_it->second.server_network_stats.has_value());
  EXPECT_EQ(new_stats_docs, *map_it->second.server_network_stats);
  ++map_it;
  EXPECT_EQ(google_server, map_it->first.server);
  EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(map_it->second.server_network_stats.has_value());
  EXPECT_EQ(stats_google, *map_it->second.server_network_stats);
  ++map_it;
  EXPECT_EQ(mail_server, map_it->first.server);
  EXPECT_TRUE(map_it->first.network_isolation_key.IsEmpty());
  ASSERT_TRUE(map_it->second.server_network_stats.has_value());
  EXPECT_EQ(stats_mail, *map_it->second.server_network_stats);
}

TEST_F(HttpServerPropertiesTest, SetServerNetworkStats) {
  url::SchemeHostPort foo_http_server("http", "foo", 443);
  url::SchemeHostPort foo_https_server("https", "foo", 443);
  EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_http_server,
                                                 NetworkIsolationKey()));
  EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
                                                 NetworkIsolationKey()));

  ServerNetworkStats stats1;
  stats1.srtt = base::TimeDelta::FromMicroseconds(10);
  stats1.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(100);
  impl_.SetServerNetworkStats(foo_http_server, NetworkIsolationKey(), stats1);

  const ServerNetworkStats* stats2 =
      impl_.GetServerNetworkStats(foo_http_server, NetworkIsolationKey());
  EXPECT_EQ(10, stats2->srtt.ToInternalValue());
  EXPECT_EQ(100, stats2->bandwidth_estimate.ToBitsPerSecond());
  // Https server should have nothing set for server network stats.
  EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
                                                 NetworkIsolationKey()));

  impl_.Clear(base::OnceClosure());
  EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_http_server,
                                                 NetworkIsolationKey()));
  EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
                                                 NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, ClearServerNetworkStats) {
  ServerNetworkStats stats;
  stats.srtt = base::TimeDelta::FromMicroseconds(10);
  stats.bandwidth_estimate = quic::QuicBandwidth::FromBitsPerSecond(100);
  url::SchemeHostPort foo_https_server("https", "foo", 443);
  impl_.SetServerNetworkStats(foo_https_server, NetworkIsolationKey(), stats);

  impl_.ClearServerNetworkStats(foo_https_server, NetworkIsolationKey());
  EXPECT_EQ(nullptr, impl_.GetServerNetworkStats(foo_https_server,
                                                 NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, OnQuicServerInfoMapLoaded) {
  quic::QuicServerId google_quic_server_id("www.google.com", 443, true);
  HttpServerProperties::QuicServerInfoMapKey google_key(
      google_quic_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);

  const int kMaxQuicServerEntries = 10;
  impl_.SetMaxServerConfigsStoredInProperties(kMaxQuicServerEntries);
  EXPECT_EQ(10u, impl_.quic_server_info_map().max_size());

  // Check empty map.
  std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
      init_quic_server_info_map =
          std::make_unique<HttpServerProperties::QuicServerInfoMap>(
              kMaxQuicServerEntries);
  impl_.OnQuicServerInfoMapLoadedForTesting(
      std::move(init_quic_server_info_map));
  EXPECT_EQ(0u, impl_.quic_server_info_map().size());

  // Check by initializing with www.google.com:443.
  std::string google_server_info("google_quic_server_info");
  init_quic_server_info_map =
      std::make_unique<HttpServerProperties::QuicServerInfoMap>(
          kMaxQuicServerEntries);
  init_quic_server_info_map->Put(google_key, google_server_info);
  impl_.OnQuicServerInfoMapLoadedForTesting(
      std::move(init_quic_server_info_map));

  // Verify data for www.google.com:443.
  EXPECT_EQ(1u, impl_.quic_server_info_map().size());
  EXPECT_EQ(
      google_server_info,
      *impl_.GetQuicServerInfo(google_quic_server_id, NetworkIsolationKey()));

  // Test recency order and overwriting of data.
  //
  // |docs_server| has a QuicServerInfo, which will be overwritten by
  // SetQuicServerInfoMap(), because |quic_server_info_map| has an
  // entry for |docs_server|.
  quic::QuicServerId docs_quic_server_id("docs.google.com", 443, true);
  HttpServerProperties::QuicServerInfoMapKey docs_key(
      docs_quic_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);
  std::string docs_server_info("docs_quic_server_info");
  impl_.SetQuicServerInfo(docs_quic_server_id, NetworkIsolationKey(),
                          docs_server_info);

  // Recency order will be |docs_server| and |google_server|.
  const HttpServerProperties::QuicServerInfoMap& map =
      impl_.quic_server_info_map();
  ASSERT_EQ(2u, map.size());
  auto map_it = map.begin();
  EXPECT_EQ(map_it->first, docs_key);
  EXPECT_EQ(docs_server_info, map_it->second);
  ++map_it;
  EXPECT_EQ(map_it->first, google_key);
  EXPECT_EQ(google_server_info, map_it->second);

  // Prepare |quic_server_info_map| to be loaded by
  // SetQuicServerInfoMap().
  std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
      quic_server_info_map =
          std::make_unique<HttpServerProperties::QuicServerInfoMap>(
              kMaxQuicServerEntries);
  // Change the values for |docs_server|.
  std::string new_docs_server_info("new_docs_quic_server_info");
  quic_server_info_map->Put(docs_key, new_docs_server_info);
  // Add data for mail.google.com:443.
  quic::QuicServerId mail_quic_server_id("mail.google.com", 443, true);
  HttpServerProperties::QuicServerInfoMapKey mail_key(
      mail_quic_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);
  std::string mail_server_info("mail_quic_server_info");
  quic_server_info_map->Put(mail_key, mail_server_info);
  impl_.OnQuicServerInfoMapLoadedForTesting(std::move(quic_server_info_map));

  // Recency order will be |docs_server|, |google_server| and |mail_server|.
  const HttpServerProperties::QuicServerInfoMap& memory_map =
      impl_.quic_server_info_map();
  ASSERT_EQ(3u, memory_map.size());
  auto memory_map_it = memory_map.begin();
  EXPECT_EQ(memory_map_it->first, docs_key);
  EXPECT_EQ(new_docs_server_info, memory_map_it->second);
  ++memory_map_it;
  EXPECT_EQ(memory_map_it->first, google_key);
  EXPECT_EQ(google_server_info, memory_map_it->second);
  ++memory_map_it;
  EXPECT_EQ(memory_map_it->first, mail_key);
  EXPECT_EQ(mail_server_info, memory_map_it->second);

  // Shrink the size of |quic_server_info_map| and verify the MRU order is
  // maintained.
  impl_.SetMaxServerConfigsStoredInProperties(2);
  EXPECT_EQ(2u, impl_.quic_server_info_map().max_size());

  const HttpServerProperties::QuicServerInfoMap& memory_map1 =
      impl_.quic_server_info_map();
  ASSERT_EQ(2u, memory_map1.size());
  auto memory_map1_it = memory_map1.begin();
  EXPECT_EQ(memory_map1_it->first, docs_key);
  EXPECT_EQ(new_docs_server_info, memory_map1_it->second);
  ++memory_map1_it;
  EXPECT_EQ(memory_map1_it->first, google_key);
  EXPECT_EQ(google_server_info, memory_map1_it->second);
  // |QuicServerInfo| for |mail_quic_server_id| shouldn't be there.
  EXPECT_EQ(nullptr, impl_.GetQuicServerInfo(mail_quic_server_id,
                                             NetworkIsolationKey()));
}

TEST_F(HttpServerPropertiesTest, SetQuicServerInfo) {
  quic::QuicServerId server1("foo", 80, false /* privacy_mode_enabled */);
  quic::QuicServerId server2("foo", 80, true /* privacy_mode_enabled */);

  std::string quic_server_info1("quic_server_info1");
  std::string quic_server_info2("quic_server_info2");
  std::string quic_server_info3("quic_server_info3");

  // Without network isolation keys enabled for HttpServerProperties, passing in
  // a NetworkIsolationKey should have no effect on behavior.
  impl_.SetQuicServerInfo(server1, NetworkIsolationKey(), quic_server_info1);
  EXPECT_EQ(quic_server_info1,
            *(impl_.GetQuicServerInfo(server1, NetworkIsolationKey())));
  EXPECT_FALSE(impl_.GetQuicServerInfo(server2, NetworkIsolationKey()));
  EXPECT_EQ(quic_server_info1,
            *(impl_.GetQuicServerInfo(server1, network_isolation_key1_)));
  EXPECT_FALSE(impl_.GetQuicServerInfo(server2, network_isolation_key1_));

  impl_.SetQuicServerInfo(server2, network_isolation_key1_, quic_server_info2);
  EXPECT_EQ(quic_server_info1,
            *(impl_.GetQuicServerInfo(server1, NetworkIsolationKey())));
  EXPECT_EQ(quic_server_info2,
            *(impl_.GetQuicServerInfo(server2, NetworkIsolationKey())));
  EXPECT_EQ(quic_server_info1,
            *(impl_.GetQuicServerInfo(server1, network_isolation_key1_)));
  EXPECT_EQ(quic_server_info2,
            *(impl_.GetQuicServerInfo(server2, network_isolation_key1_)));

  impl_.SetQuicServerInfo(server1, network_isolation_key1_, quic_server_info3);
  EXPECT_EQ(quic_server_info3,
            *(impl_.GetQuicServerInfo(server1, NetworkIsolationKey())));
  EXPECT_EQ(quic_server_info2,
            *(impl_.GetQuicServerInfo(server2, NetworkIsolationKey())));
  EXPECT_EQ(quic_server_info3,
            *(impl_.GetQuicServerInfo(server1, network_isolation_key1_)));
  EXPECT_EQ(quic_server_info2,
            *(impl_.GetQuicServerInfo(server2, network_isolation_key1_)));

  impl_.Clear(base::OnceClosure());
  EXPECT_FALSE(impl_.GetQuicServerInfo(server1, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetQuicServerInfo(server2, NetworkIsolationKey()));
  EXPECT_FALSE(impl_.GetQuicServerInfo(server1, network_isolation_key1_));
  EXPECT_FALSE(impl_.GetQuicServerInfo(server2, network_isolation_key1_));

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  properties.SetQuicServerInfo(server1, NetworkIsolationKey(),
                               quic_server_info1);
  EXPECT_EQ(quic_server_info1,
            *(properties.GetQuicServerInfo(server1, NetworkIsolationKey())));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key1_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));

  properties.SetQuicServerInfo(server1, network_isolation_key1_,
                               quic_server_info2);
  EXPECT_EQ(quic_server_info1,
            *(properties.GetQuicServerInfo(server1, NetworkIsolationKey())));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
  EXPECT_EQ(quic_server_info2,
            *(properties.GetQuicServerInfo(server1, network_isolation_key1_)));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));

  properties.SetQuicServerInfo(server2, network_isolation_key1_,
                               quic_server_info3);
  EXPECT_EQ(quic_server_info1,
            *(properties.GetQuicServerInfo(server1, NetworkIsolationKey())));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
  EXPECT_EQ(quic_server_info2,
            *(properties.GetQuicServerInfo(server1, network_isolation_key1_)));
  EXPECT_EQ(quic_server_info3,
            *(properties.GetQuicServerInfo(server2, network_isolation_key1_)));

  properties.Clear(base::OnceClosure());
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key1_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));
}

// Tests that GetQuicServerInfo() returns server info of a host
// with the same canonical suffix when there is no exact host match.
TEST_F(HttpServerPropertiesTest, QuicServerInfoCanonicalSuffixMatch) {
  // Set up HttpServerProperties.
  // Add a host with a canonical suffix.
  quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
  std::string foo_server_info("foo_server_info");
  impl_.SetQuicServerInfo(foo_server_id, NetworkIsolationKey(),
                          foo_server_info);

  // Add a host that has a different canonical suffix.
  quic::QuicServerId baz_server_id("baz.video.com", 443, false);
  std::string baz_server_info("baz_server_info");
  impl_.SetQuicServerInfo(baz_server_id, NetworkIsolationKey(),
                          baz_server_info);

  // Create SchemeHostPort with a host that has the initial canonical suffix.
  quic::QuicServerId bar_server_id("bar.googlevideo.com", 443, false);

  // Check the the server info associated with "foo" is returned for "bar".
  const std::string* bar_server_info =
      impl_.GetQuicServerInfo(bar_server_id, NetworkIsolationKey());
  ASSERT_TRUE(bar_server_info != nullptr);
  EXPECT_EQ(foo_server_info, *bar_server_info);
}

// Make sure that canonical suffices respect NetworkIsolationKeys when using
// QuicServerInfo methods.
TEST_F(HttpServerPropertiesTest,
       QuicServerInfoCanonicalSuffixMatchWithNetworkIsolationKey) {
  // Two servers with same canonical suffix.
  quic::QuicServerId server1("foo.googlevideo.com", 80,
                             false /* privacy_mode_enabled */);
  quic::QuicServerId server2("bar.googlevideo.com", 80,
                             false /* privacy_mode_enabled */);

  std::string server_info1("server_info1");
  std::string server_info2("server_info2");

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  HttpServerProperties properties(nullptr /* pref_delegate */,
                                  nullptr /* net_log */, test_tick_clock_,
                                  &test_clock_);

  // Set QuicServerInfo for one canononical suffix and
  // |network_isolation_key1_|. It should be accessible via another
  // SchemeHostPort, but only when the NetworkIsolationKeys match.
  properties.SetQuicServerInfo(server1, network_isolation_key1_, server_info1);
  const std::string* fetched_server_info =
      properties.GetQuicServerInfo(server1, network_isolation_key1_);
  ASSERT_TRUE(fetched_server_info);
  EXPECT_EQ(server_info1, *fetched_server_info);
  fetched_server_info =
      properties.GetQuicServerInfo(server2, network_isolation_key1_);
  ASSERT_TRUE(fetched_server_info);
  EXPECT_EQ(server_info1, *fetched_server_info);
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key2_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key2_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));

  // Set different QuicServerInfo for the same canononical suffix and
  // |network_isolation_key2_|. Both infos should be retriveable by using the
  // different NetworkIsolationKeys.
  properties.SetQuicServerInfo(server1, network_isolation_key2_, server_info2);
  fetched_server_info =
      properties.GetQuicServerInfo(server1, network_isolation_key1_);
  ASSERT_TRUE(fetched_server_info);
  EXPECT_EQ(server_info1, *fetched_server_info);
  fetched_server_info =
      properties.GetQuicServerInfo(server2, network_isolation_key1_);
  ASSERT_TRUE(fetched_server_info);
  EXPECT_EQ(server_info1, *fetched_server_info);
  fetched_server_info =
      properties.GetQuicServerInfo(server1, network_isolation_key2_);
  ASSERT_TRUE(fetched_server_info);
  EXPECT_EQ(server_info2, *fetched_server_info);
  fetched_server_info =
      properties.GetQuicServerInfo(server2, network_isolation_key2_);
  ASSERT_TRUE(fetched_server_info);
  EXPECT_EQ(server_info2, *fetched_server_info);
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));

  // Clearing should destroy all information.
  properties.Clear(base::OnceClosure());
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key1_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key1_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, network_isolation_key2_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, network_isolation_key2_));
  EXPECT_FALSE(properties.GetQuicServerInfo(server1, NetworkIsolationKey()));
  EXPECT_FALSE(properties.GetQuicServerInfo(server2, NetworkIsolationKey()));
}

// Verifies that GetQuicServerInfo() returns the MRU entry if multiple records
// match a given canonical host.
TEST_F(HttpServerPropertiesTest,
       QuicServerInfoCanonicalSuffixMatchReturnsMruEntry) {
  // Set up HttpServerProperties by adding two hosts with the same canonical
  // suffixes.
  quic::QuicServerId h1_server_id("h1.googlevideo.com", 443, false);
  std::string h1_server_info("h1_server_info");
  impl_.SetQuicServerInfo(h1_server_id, NetworkIsolationKey(), h1_server_info);

  quic::QuicServerId h2_server_id("h2.googlevideo.com", 443, false);
  std::string h2_server_info("h2_server_info");
  impl_.SetQuicServerInfo(h2_server_id, NetworkIsolationKey(), h2_server_info);

  // Create quic::QuicServerId to use for the search.
  quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);

  // Check that 'h2' info is returned since it is MRU.
  const std::string* server_info =
      impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
  ASSERT_TRUE(server_info != nullptr);
  EXPECT_EQ(h2_server_info, *server_info);

  // Access 'h1' info, so it becomes MRU.
  impl_.GetQuicServerInfo(h1_server_id, NetworkIsolationKey());

  // Check that 'h1' info is returned since it is MRU now.
  server_info = impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
  ASSERT_TRUE(server_info != nullptr);
  EXPECT_EQ(h1_server_info, *server_info);
}

// Verifies that |GetQuicServerInfo| doesn't change the MRU order of the server
// info map when a record is matched based on a canonical name.
TEST_F(HttpServerPropertiesTest,
       QuicServerInfoCanonicalSuffixMatchDoesntChangeOrder) {
  // Add a host with a matching canonical name.
  quic::QuicServerId h1_server_id("h1.googlevideo.com", 443, false);
  HttpServerProperties::QuicServerInfoMapKey h1_key(
      h1_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);
  std::string h1_server_info("h1_server_info");
  impl_.SetQuicServerInfo(h1_server_id, NetworkIsolationKey(), h1_server_info);

  // Add a host hosts with a non-matching canonical name.
  quic::QuicServerId h2_server_id("h2.video.com", 443, false);
  HttpServerProperties::QuicServerInfoMapKey h2_key(
      h2_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);
  std::string h2_server_info("h2_server_info");
  impl_.SetQuicServerInfo(h2_server_id, NetworkIsolationKey(), h2_server_info);

  // Check that "h2.video.com" is the MRU entry in the map.
  EXPECT_EQ(h2_key, impl_.quic_server_info_map().begin()->first);

  // Search for the entry that matches the canonical name
  // ("h1.googlevideo.com").
  quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
  const std::string* server_info =
      impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
  ASSERT_TRUE(server_info != nullptr);

  // Check that the search (although successful) hasn't changed the MRU order of
  // the map.
  EXPECT_EQ(h2_key, impl_.quic_server_info_map().begin()->first);

  // Search for "h1.googlevideo.com" directly, so it becomes MRU
  impl_.GetQuicServerInfo(h1_server_id, NetworkIsolationKey());

  // Check that "h1.googlevideo.com" is the MRU entry now.
  EXPECT_EQ(h1_key, impl_.quic_server_info_map().begin()->first);
}

// Tests that the canonical host matching works for hosts stored in memory cache
// and the ones loaded from persistent storage, i.e. server info added
// using SetQuicServerInfo() and SetQuicServerInfoMap() is taken into
// cosideration when searching for server info for a host with the same
// canonical suffix.
TEST_F(HttpServerPropertiesTest, QuicServerInfoCanonicalSuffixMatchSetInfoMap) {
  // Add a host info using SetQuicServerInfo(). That will simulate an info
  // entry stored in memory cache.
  quic::QuicServerId h1_server_id("h1.googlevideo.com", 443, false);
  std::string h1_server_info("h1_server_info_memory_cache");
  impl_.SetQuicServerInfo(h1_server_id, NetworkIsolationKey(), h1_server_info);

  // Prepare a map with host info and add it using SetQuicServerInfoMap(). That
  // will simulate info records read from the persistence storage.
  quic::QuicServerId h2_server_id("h2.googlevideo.com", 443, false);
  HttpServerProperties::QuicServerInfoMapKey h2_key(
      h2_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);
  std::string h2_server_info("h2_server_info_from_disk");

  quic::QuicServerId h3_server_id("h3.ggpht.com", 443, false);
  HttpServerProperties::QuicServerInfoMapKey h3_key(
      h3_server_id, NetworkIsolationKey(),
      false /* use_network_isolation_key */);
  std::string h3_server_info("h3_server_info_from_disk");

  const int kMaxQuicServerEntries = 10;
  impl_.SetMaxServerConfigsStoredInProperties(kMaxQuicServerEntries);

  std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
      quic_server_info_map =
          std::make_unique<HttpServerProperties::QuicServerInfoMap>(
              kMaxQuicServerEntries);
  quic_server_info_map->Put(h2_key, h2_server_info);
  quic_server_info_map->Put(h3_key, h3_server_info);
  impl_.OnQuicServerInfoMapLoadedForTesting(std::move(quic_server_info_map));

  // Check that the server info from the memory cache is returned since unique
  // entries from the memory cache are added after entries from the
  // persistence storage and, therefore, are most recently used.
  quic::QuicServerId foo_server_id("foo.googlevideo.com", 443, false);
  const std::string* server_info =
      impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
  ASSERT_TRUE(server_info != nullptr);
  EXPECT_EQ(h1_server_info, *server_info);

  // Check that server info that was added using SetQuicServerInfoMap() can be
  // found.
  foo_server_id = quic::QuicServerId("foo.ggpht.com", 443, false);
  server_info = impl_.GetQuicServerInfo(foo_server_id, NetworkIsolationKey());
  ASSERT_TRUE(server_info != nullptr);
  EXPECT_EQ(h3_server_info, *server_info);
}

}  // namespace

}  // namespace net
