// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/omnibox/browser/zero_suggest_verbatim_match_provider.h"

#include <memory>
#include <string>

#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "build/android_buildflags.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/dom_distiller/core/url_utils.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_types.h"
#include "components/omnibox/browser/autocomplete_enums.h"
#include "components/omnibox/browser/fake_autocomplete_provider_client.h"
#include "components/omnibox/browser/mock_autocomplete_provider_client.h"
#include "components/omnibox/browser/test_scheme_classifier.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/search_engines/search_engines_test_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "ui/base/device_form_factor.h"

namespace {
#if BUILDFLAG(IS_ANDROID)
std::unique_ptr<TemplateURLData> GenerateSimpleTemplateURLData(
    const std::string& keyword) {
  auto data = std::make_unique<TemplateURLData>();
  data->SetShortName(base::UTF8ToUTF16(keyword));
  data->SetKeyword(base::UTF8ToUTF16(keyword));
  data->SetURL(std::string("https://") + keyword + "/q={searchTerms}");
  return data;
}
#endif

using testing::_;

class MockHistoryService : public history::HistoryService {
 public:
  MockHistoryService() = default;
  ~MockHistoryService() override = default;

  MOCK_METHOD(base::CancelableTaskTracker::TaskId,
              QueryURL,
              (const GURL& url,
               history::HistoryService::QueryURLCallback callback,
               base::CancelableTaskTracker* tracker),
              (override));
};
}  // namespace

class ZeroSuggestVerbatimMatchProviderTest
    : public testing::TestWithParam<
          metrics::OmniboxEventProto::PageClassification> {
 public:
  ZeroSuggestVerbatimMatchProviderTest() = default;
  void SetUp() override;

 protected:
  bool IsVerbatimMatchEligible() const;
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::MainThreadType::UI};
  FakeAutocompleteProviderClient mock_client_;
  scoped_refptr<ZeroSuggestVerbatimMatchProvider> provider_;
};

bool ZeroSuggestVerbatimMatchProviderTest::IsVerbatimMatchEligible() const {
  using OEP = metrics::OmniboxEventProto;

  auto param = GetParam();
  return param == OEP::OTHER || param == OEP::OTHER_ON_CCT ||
         param == OEP::SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT ||
         param == OEP::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT ||
         param == OEP::SEARCH_RESULT_PAGE_ON_CCT;
}

void ZeroSuggestVerbatimMatchProviderTest::SetUp() {
#if BUILDFLAG(IS_DESKTOP_ANDROID)
  GTEST_SKIP() << "No zero-suggest verbatim match on Android Desktop.";
#else   // IS_DESKTOP_ANDROID
  provider_ = new ZeroSuggestVerbatimMatchProvider(&mock_client_);
  ON_CALL(mock_client_, IsOffTheRecord()).WillByDefault([] { return false; });
  ON_CALL(mock_client_, Classify)
      .WillByDefault(
          [](const std::u16string& text, bool in_keyword_mode,
             bool allow_exact_keyword_match,
             metrics::OmniboxEventProto::PageClassification page_classification,
             AutocompleteMatch* match,
             GURL* alternate_nav_url) { match->destination_url = GURL(text); });
#endif  // IS_DESKTOP_ANDROID
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       NoVerbatimMatchWithUserTextInOmnibox) {
  std::string query("user input");
  std::string url("https://google.com/search?q=test");
  AutocompleteInput input(base::ASCIIToUTF16(query), GetParam(),
                          TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_DEFAULT);
  provider_->Start(input, false);

  // Given user text in omnibox, never generate a verbatim match.
  EXPECT_TRUE(provider_->matches().empty());
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       NoVerbatimMatchWithUserTextInOmniboxInIncognito) {
  std::string query("user input");
  std::string url("https://google.com/search?q=test");
  AutocompleteInput input(base::ASCIIToUTF16(query), GetParam(),
                          TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_DEFAULT);
  ON_CALL(mock_client_, IsOffTheRecord()).WillByDefault([] { return true; });
  provider_->Start(input, false);

  // Given user text in omnibox, never generate a verbatim match.
  EXPECT_TRUE(provider_->matches().empty());
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest, OffersVerbatimMatchOnFocus) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(base::ASCIIToUTF16(url), GetParam(),
                          TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  ASSERT_EQ(IsVerbatimMatchEligible(), provider_->matches().size() > 0);
  // Note: we intentionally do not validate the match content here.
  // The content is populated either by HistoryURLProvider or
  // AutocompleteProviderClient both of which we would have to mock for this
  // test. As a result, the test would validate what the mocks fill in.
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       OffersVerbatimMatchOnFocusInIncognito) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(base::ASCIIToUTF16(url), GetParam(),
                          TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  ON_CALL(mock_client_, IsOffTheRecord()).WillByDefault([] { return true; });
  provider_->Start(input, false);
  ASSERT_EQ(IsVerbatimMatchEligible(), provider_->matches().size() > 0);
  // Note: we intentionally do not validate the match content here.
  // The content is populated either by HistoryURLProvider or
  // AutocompleteProviderClient both of which we would have to mock for this
  // test. As a result, the test would validate what the mocks fill in.
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest, NoVerbatimMatchWithEmptyInput) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_DEFAULT);
  provider_->Start(input, false);
  ASSERT_TRUE(provider_->matches().empty());
  // Note: we intentionally do not validate the match content here.
  // The content is populated either by HistoryURLProvider or
  // AutocompleteProviderClient both of which we would have to mock for this
  // test. As a result, the test would validate what the mocks fill in.
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       NoVerbatimMatchWithEmptyInputInIncognito) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_DEFAULT);
  ON_CALL(mock_client_, IsOffTheRecord()).WillByDefault([] { return true; });
  provider_->Start(input, false);
  ASSERT_TRUE(provider_->matches().empty());
  // Note: we intentionally do not validate the match content here.
  // The content is populated either by HistoryURLProvider or
  // AutocompleteProviderClient both of which we would have to mock for this
  // test. As a result, the test would validate what the mocks fill in.
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       OffersVerbatimMatchOnFocusAndEmpty) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  ASSERT_EQ(IsVerbatimMatchEligible(), provider_->matches().size() > 0);
  // Note: we intentionally do not validate the match content here.
  // The content is populated either by HistoryURLProvider or
  // AutocompleteProviderClient both of which we would have to mock for this
  // test. As a result, the test would validate what the mocks fill in.
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       OffersVerbatimMatchOnFocusAndEmptyInIncognito) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  ON_CALL(mock_client_, IsOffTheRecord()).WillByDefault([] { return true; });
  provider_->Start(input, false);
  ASSERT_EQ(IsVerbatimMatchEligible(), provider_->matches().size() > 0);
  // Note: we intentionally do not validate the match content here.
  // The content is populated either by HistoryURLProvider or
  // AutocompleteProviderClient both of which we would have to mock for this
  // test. As a result, the test would validate what the mocks fill in.
}

#if !BUILDFLAG(IS_ANDROID)
TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       DoesNotAttemptToPopulateFillIntoEditWithFeatureDisabled) {
  base::test::ScopedFeatureList features;
  // Clear the TemplateURLService. Observe crash, if we attempt to use it.
  mock_client_.set_template_url_service(nullptr);

  std::string url("https://www.wider.com/");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wider.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"title", provider_->matches()[0].description);
  }
}
#endif

#if BUILDFLAG(IS_ANDROID)
TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       NoFillIntoEditResolutionWithNoSearchEngines) {
  base::test::ScopedFeatureList features;
  std::string url("https://www.search.com/q=abc");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.search.com/q=abc",
              provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"title", provider_->matches()[0].description);
  }
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       UpdateFillIntoEditWhenUrlMatchesSearchResultsPage) {
  base::test::ScopedFeatureList features;

  // Default TemplateURL to parse the URL.
  std::unique_ptr<TemplateURLData> engine =
      GenerateSimpleTemplateURLData("www.search.com");
  mock_client_.GetTemplateURLService()->ApplyDefaultSearchChangeForTesting(
      engine.get(), DefaultSearchManager::FROM_USER);

  std::string url("https://www.search.com/q=abc");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"abc", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"title", provider_->matches()[0].description);
  }
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       UpdateFillIntoEditWhenUrlMatchesSearchResultsPageWithTrailingSpace) {
  base::test::ScopedFeatureList features;

  // Default TemplateURL to parse the URL.
  std::unique_ptr<TemplateURLData> engine =
      GenerateSimpleTemplateURLData("www.search.com");
  mock_client_.GetTemplateURLService()->ApplyDefaultSearchChangeForTesting(
      engine.get(), DefaultSearchManager::FROM_USER);

  // Ensure URLs with trailing escaped whitespace (%20) are correctly sanitized
  // upon search term extraction to avoid AutocompleteResult DCHECK crashes.
  std::string url("https://www.search.com/q=abc%20");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"abc", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"abc", provider_->matches()[0].contents);
    ASSERT_EQ(u"title", provider_->matches()[0].description);
  }
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       DontUpdateFillIntoEditWhenUrlMatchesNonDefaultSearchEngine) {
  base::test::ScopedFeatureList features;

  // Default TemplateURL to parse the URL.
  std::unique_ptr<TemplateURLData> engine =
      GenerateSimpleTemplateURLData("www.search.com");
  // Other search engines.
  TemplateURLService::Initializer other_engines[] = {
      {"non-default", "https://www.non-default.com/q=abc", "non-default"}};
  search_engines::SearchEnginesTestEnvironment test_environment(
      {.template_url_service_initializer = other_engines});
  mock_client_.set_template_url_service(
      test_environment.template_url_service());
  mock_client_.GetTemplateURLService()->ApplyDefaultSearchChangeForTesting(
      engine.get(), DefaultSearchManager::FROM_USER);

  std::string url("https://www.non-default.com/q=abc");
  AutocompleteInput input(std::u16string(),  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);
  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.non-default.com/q=abc",
              provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"title", provider_->matches()[0].description);
  }

  // `mock_client_` points to the `TemplateURLService` found in
  // `test_environment`, which is going out of scope here.
  // Destroy it to avoid dangling pointers.
  mock_client_.set_template_url_service(nullptr);
}
TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       UpdateFillIntoEditWhenUrlIsDistilledPage) {
  GURL original_url("https://www.wired.com/article");

  GURL distilled_url = dom_distiller::url_utils::GetDistillerViewUrlFromUrl(
      dom_distiller::kDomDistillerScheme, original_url, "");

  AutocompleteInput input(std::u16string(), GetParam(), TestSchemeClassifier());
  input.set_current_title(u"title");
  input.set_current_url(distilled_url);
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);

  GURL extracted_original_url =
      dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl(distilled_url);

  ASSERT_TRUE(extracted_original_url.is_valid());

  provider_->Start(input, false);

  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    const auto& match = provider_->matches()[0];
    EXPECT_EQ(base::UTF8ToUTF16(extracted_original_url.spec()),
              match.fill_into_edit);
    EXPECT_EQ(u"wired.com/article", match.contents);
    EXPECT_EQ(u"title", match.description);
  }
}
#endif

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       MissingPageTitle_NoHistoryService) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(u"",  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  // Note: no page title.
  input.set_current_title(u"");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
  provider_->Start(input, false);

  if (IsVerbatimMatchEligible()) {
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wired.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"", provider_->matches()[0].description);
  }
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       MissingPageTitle_WithHistoryService) {
  // Install history service mock.
  auto mock_service_up = std::make_unique<MockHistoryService>();
  auto& mock_service = *mock_service_up;
  mock_client_.set_history_service(std::move(mock_service_up));

  std::string url("https://www.wired.com/");
  AutocompleteInput input(u"",  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  // Note: no page title.
  input.set_current_title(u"");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);

  if (!IsVerbatimMatchEligible()) {
    return;
  }

  history::HistoryService::QueryURLCallback callback;
  {
    EXPECT_CALL(mock_service, QueryURL(_, _, _))
        .WillOnce([&](GURL url, history::HistoryService::QueryURLCallback cb,
                      base::CancelableTaskTracker* tracker)
                      -> base::CancelableTaskTracker::TaskId {
          EXPECT_EQ("https://www.wired.com/", url.spec());
          callback = std::move(cb);
          return {};
        });
    provider_->Start(input, false);

    // Default matches with no title.
    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wired.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"", provider_->matches()[0].description);
  }

  {
    // Resolve history service.
    history::QueryURLResult history_row;
    history_row.row.set_title(u"Testing");
    std::move(callback).Run(std::move(history_row));

    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wired.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"Testing", provider_->matches()[0].description);
  }
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       MissingPageTitle_WithHistoryService_Synchronous) {
  // Install history service mock.
  auto mock_service_up = std::make_unique<MockHistoryService>();
  auto& mock_service = *mock_service_up;
  mock_client_.set_history_service(std::move(mock_service_up));

  std::string url("https://www.wired.com/");
  AutocompleteInput input(u"",  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  // Note: no page title.
  input.set_current_title(u"");
  input.set_omit_asynchronous_matches(true);
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);

  if (!IsVerbatimMatchEligible()) {
    return;
  }

  {
    EXPECT_CALL(mock_service, QueryURL(_, _, _)).Times(0);
    provider_->Start(input, false);

    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wired.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"", provider_->matches()[0].description);
  }
}

TEST_P(ZeroSuggestVerbatimMatchProviderTest,
       MissingPageTitle_CallbackCanceled) {
  // Install history service mock.
  auto mock_service_up = std::make_unique<MockHistoryService>();
  auto& mock_service = *mock_service_up;
  mock_client_.set_history_service(std::move(mock_service_up));

  std::string url("https://www.wired.com/");
  AutocompleteInput input(u"",  // Note: empty input.
                          GetParam(), TestSchemeClassifier());
  // Note: no page title.
  input.set_current_title(u"");
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);

  if (!IsVerbatimMatchEligible()) {
    return;
  }

  history::HistoryService::QueryURLCallback callback;
  {
    EXPECT_CALL(mock_service, QueryURL(_, _, _))
        .WillOnce([&](GURL url, history::HistoryService::QueryURLCallback cb,
                      base::CancelableTaskTracker* tracker)
                      -> base::CancelableTaskTracker::TaskId {
          EXPECT_EQ("https://www.wired.com/", url.spec());
          callback = std::move(cb);
          return {};
        });
    provider_->Start(input, false);

    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wired.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"", provider_->matches()[0].description);
  }

  // Cancel action.
  provider_->Stop(AutocompleteStopReason::kInteraction);

  {
    // Resolve history service.
    // Expect NO AutocompleteMatch.
    history::QueryURLResult history_row;
    history_row.row.set_title(u"Testing");
    std::move(callback).Run(std::move(history_row));

    ASSERT_FALSE(provider_->matches().empty());
    ASSERT_EQ(u"https://www.wired.com", provider_->matches()[0].fill_into_edit);
    ASSERT_EQ(u"", provider_->matches()[0].description);
  }
}

class ZeroSuggestVerbatimMatchProviderComposeboxTest : public testing::Test {
 protected:
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::MainThreadType::UI};
  FakeAutocompleteProviderClient mock_client_;
  scoped_refptr<ZeroSuggestVerbatimMatchProvider> provider_;

  void SetUp() override {
    provider_ = new ZeroSuggestVerbatimMatchProvider(&mock_client_);
  }
};

TEST_F(ZeroSuggestVerbatimMatchProviderComposeboxTest,
       CreatesVerbatimMatchForComposeboxWithInputs) {
  AutocompleteInput input(std::u16string(),
                          metrics::OmniboxEventProto::NTP_COMPOSEBOX,
                          TestSchemeClassifier());
  input.set_current_url(GURL("https://www.wired.com/"));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);

  // Set lens overlay suggest inputs.
  lens::proto::LensOverlaySuggestInputs suggest_inputs;
  suggest_inputs.set_encoded_image_signals("test_signals");
  input.set_lens_overlay_suggest_inputs(suggest_inputs);

  provider_->Start(input, false);

  ASSERT_EQ(1u, provider_->matches().size());
  const auto& match = provider_->matches()[0];
  EXPECT_TRUE(match.search_terms_args);
}

TEST_F(ZeroSuggestVerbatimMatchProviderComposeboxTest,
       NoMatchForComposeboxWithoutInputs) {
  std::string url("https://www.wired.com/");
  AutocompleteInput input(std::u16string(),
                          metrics::OmniboxEventProto::NTP_COMPOSEBOX,
                          TestSchemeClassifier());
  input.set_current_url(GURL(url));
  input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);

  provider_->Start(input, false);

  ASSERT_TRUE(provider_->matches().empty());
}

INSTANTIATE_TEST_SUITE_P(
    ZeroSuggestVerbatimMatchProviderNonIncognitoTests,
    ZeroSuggestVerbatimMatchProviderTest,
    ::testing::Values(
        // Variants that should offer verbatim match.
        metrics::OmniboxEventProto::OTHER,
        metrics::OmniboxEventProto::
            SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT,
        metrics::OmniboxEventProto::
            SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT,

        // Variants that should offer no verbatim match.
        metrics::OmniboxEventProto::NTP,
        metrics::OmniboxEventProto::BLANK,
        metrics::OmniboxEventProto::HOME_PAGE,
        metrics::OmniboxEventProto::OTHER_ON_CCT,
        metrics::OmniboxEventProto::SEARCH_RESULT_PAGE_ON_CCT,
        metrics::OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS),

    // Ensure clarity when error message is printed out.
    +[](const ::testing::TestParamInfo<
         metrics::OmniboxEventProto::PageClassification> context)
        -> std::string {
      return metrics::OmniboxEventProto::PageClassification_Name(context.param);
    });
