| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/task_environment.h" |
| #include "base/values.h" |
| #include "base/version_info/version_info.h" |
| #include "components/country_codes/country_codes.h" |
| #include "components/search_engines/keyword_web_data_service.h" |
| #include "components/search_engines/prepopulated_engines.h" |
| #include "components/search_engines/search_engine_choice/search_engine_choice_service.h" |
| #include "components/search_engines/search_engines_pref_names.h" |
| #include "components/search_engines/search_engines_switches.h" |
| #include "components/search_engines/search_terms_data.h" |
| #include "components/search_engines/template_url.h" |
| #include "components/search_engines/template_url_prepopulate_data.h" |
| #include "components/search_engines/template_url_service.h" |
| #include "components/search_engines/template_url_starter_pack_data.h" |
| #include "components/search_engines/util.h" |
| #include "components/signin/public/base/signin_switches.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "components/webdata/common/web_database_service.h" |
| #include "components/webdata/common/webdata_constants.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| std::unique_ptr<TemplateURLData> CreatePrepopulateTemplateURLData( |
| int prepopulate_id, |
| const std::string& keyword) { |
| return std::make_unique<TemplateURLData>( |
| u"Search engine name", base::ASCIIToUTF16(keyword), "https://search.url", |
| "" /* suggest_url */, "" /* image_url */, "" /* image_translate_url */, |
| "" /* new_tab_url */, "" /* contextual_search_url */, "" /* logo_url */, |
| "" /* doodle_url */, "" /* search_url_post_params */, |
| "" /* suggest_url_post_params */, "" /* image_url_post_params */, |
| "" /* side_search_param */, "" /* side_image_search_param */, |
| "" /* image_translate_source_language_param_key */, |
| "" /* image_translate_target_language_param_key */, |
| std::vector<std::string>() /* search_intent_params */, |
| "" /* favicon_url */, "UTF-8", u"" /* image_search_branding_label */, |
| base::Value::List() /* alternate_urls_list */, |
| false /* preconnect_to_search_url */, |
| false /* prefetch_likely_navigations */, prepopulate_id); |
| } |
| |
| // Creates a TemplateURL with default values except for the prepopulate ID, |
| // keyword and TemplateURLID. Only use this in tests if your tests do not |
| // care about other fields. |
| std::unique_ptr<TemplateURL> CreatePrepopulateTemplateURL( |
| int prepopulate_id, |
| const std::string& keyword, |
| TemplateURLID id, |
| bool is_play_api_turl = false) { |
| std::unique_ptr<TemplateURLData> data = |
| CreatePrepopulateTemplateURLData(prepopulate_id, keyword); |
| data->id = id; |
| data->created_from_play_api = is_play_api_turl; |
| return std::make_unique<TemplateURL>(*data); |
| } |
| |
| // Sets up dependencies and calls `GetSearchProvidersUsingLoadedEngines()`. |
| // As with the wrapped function, `template_urls` will be updated with the loaded |
| // engines, including the starter pack ones, and `*resource_keyword_version` |
| // will be set to the version number for the loaded data or to 0 if no |
| // prepopulated engines were loaded. |
| void CallGetSearchProvidersUsingLoadedEngines( |
| PrefService* prefs, |
| search_engines::SearchEngineChoiceService* search_engine_choice_service, |
| TemplateURLService::OwnedTemplateURLVector* template_urls, |
| WDKeywordsResult::Metadata& inout_resource_metadata) { |
| // Setup inspired by `//components/webdata_services/web_data_service_wrapper*` |
| |
| base::test::TaskEnvironment task_environment{ |
| base::test::TaskEnvironment::MainThreadType::UI}; |
| auto task_runner = task_environment.GetMainThreadTaskRunner(); |
| |
| base::ScopedTempDir scoped_temp_dir; |
| ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); |
| |
| auto profile_database = base::MakeRefCounted<WebDatabaseService>( |
| scoped_temp_dir.GetPath().Append(kWebDataFilename), |
| /*ui_task_runner=*/task_runner, |
| /*db_task_runner=*/task_runner); |
| profile_database->AddTable(std::make_unique<KeywordTable>()); |
| profile_database->LoadDatabase(); |
| |
| auto keyword_web_data = base::MakeRefCounted<KeywordWebDataService>( |
| profile_database, task_runner); |
| keyword_web_data->Init(base::DoNothing()); |
| |
| { |
| SearchTermsData search_terms_data; |
| std::set<std::string> removed_keyword_guids; |
| |
| GetSearchProvidersUsingLoadedEngines( |
| keyword_web_data.get(), prefs, search_engine_choice_service, |
| template_urls, |
| /*default_search_provider=*/nullptr, search_terms_data, |
| inout_resource_metadata, &removed_keyword_guids); |
| |
| EXPECT_TRUE(removed_keyword_guids.empty()); |
| } |
| |
| keyword_web_data->ShutdownOnUISequence(); |
| profile_database->ShutdownDatabase(); |
| } |
| |
| } // namespace |
| |
| TEST(TemplateURLServiceUtilTest, RemoveDuplicatePrepopulateIDs) { |
| std::vector<std::unique_ptr<TemplateURLData>> prepopulated_turls; |
| TemplateURLService::OwnedTemplateURLVector local_turls; |
| |
| prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(1, "winner4")); |
| prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(2, "xxx")); |
| prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(3, "yyy")); |
| |
| // Create a sets of different TURLs grouped by prepopulate ID. Each group |
| // will test a different heuristic of RemoveDuplicatePrepopulateIDs. |
| // Ignored set - These should be left alone as they do not have valid |
| // prepopulate IDs. |
| local_turls.push_back(CreatePrepopulateTemplateURL(0, "winner1", 4)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(0, "winner2", 5)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(0, "winner3", 6)); |
| size_t num_non_prepopulated_urls = local_turls.size(); |
| |
| // Keyword match set - Prefer the one that matches the keyword of the |
| // prepopulate ID. |
| local_turls.push_back(CreatePrepopulateTemplateURL(1, "loser1", 7)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(1, "loser2", 8)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(1, "winner4", 9)); |
| |
| // Default set - Prefer the default search engine over all other criteria. |
| // The last one is the default. It will be passed as the |
| // default_search_provider parameter to RemoveDuplicatePrepopulateIDs. |
| local_turls.push_back(CreatePrepopulateTemplateURL(2, "loser3", 10)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(2, "xxx", 11)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(2, "winner5", 12)); |
| TemplateURL* default_turl = local_turls.back().get(); |
| |
| // ID set - Prefer the lowest TemplateURLID if the keywords don't match and if |
| // none are the default. |
| local_turls.push_back(CreatePrepopulateTemplateURL(3, "winner6", 13)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(3, "loser5", 14)); |
| local_turls.push_back(CreatePrepopulateTemplateURL(3, "loser6", 15)); |
| |
| RemoveDuplicatePrepopulateIDs(nullptr, prepopulated_turls, default_turl, |
| &local_turls, SearchTermsData(), nullptr); |
| |
| // Verify that the expected local TURLs survived the process. |
| EXPECT_EQ(local_turls.size(), |
| prepopulated_turls.size() + num_non_prepopulated_urls); |
| for (const auto& turl : local_turls) { |
| EXPECT_TRUE(base::StartsWith(turl->keyword(), u"winner", |
| base::CompareCase::SENSITIVE)); |
| } |
| } |
| |
| // Tests correct interaction of Play API search engine during prepopulated list |
| // update. |
| TEST(TemplateURLServiceUtilTest, MergeEnginesFromPrepopulateData_PlayAPI) { |
| std::vector<std::unique_ptr<TemplateURLData>> prepopulated_turls; |
| TemplateURLService::OwnedTemplateURLVector local_turls; |
| |
| // Start with single search engine created from Play API data. |
| local_turls.push_back(CreatePrepopulateTemplateURL(0, "play", 1, true)); |
| |
| // Test that prepopulated search engine with matching keyword is merged with |
| // Play API search engine. Search URL should come from Play API search engine. |
| const std::string prepopulated_search_url = "http://prepopulated.url"; |
| prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(1, "play")); |
| prepopulated_turls.back()->SetURL(prepopulated_search_url); |
| MergeEnginesFromPrepopulateData(nullptr, &prepopulated_turls, &local_turls, |
| nullptr, nullptr); |
| ASSERT_EQ(local_turls.size(), 1U); |
| // Merged search engine should have both Play API flag and valid |
| // prepopulate_id. |
| EXPECT_TRUE(local_turls[0]->created_from_play_api()); |
| EXPECT_EQ(1, local_turls[0]->prepopulate_id()); |
| EXPECT_NE(prepopulated_search_url, local_turls[0]->url()); |
| |
| // Test that merging prepopulated search engine with matching prepopulate_id |
| // preserves keyword of Play API search engine. |
| prepopulated_turls.clear(); |
| prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(1, "play2")); |
| MergeEnginesFromPrepopulateData(nullptr, &prepopulated_turls, &local_turls, |
| nullptr, nullptr); |
| ASSERT_EQ(local_turls.size(), 1U); |
| EXPECT_TRUE(local_turls[0]->created_from_play_api()); |
| EXPECT_EQ(local_turls[0]->keyword(), u"play"); |
| |
| // Test that removing search engine from prepopulated list doesn't delete Play |
| // API search engine record. |
| prepopulated_turls.clear(); |
| MergeEnginesFromPrepopulateData(nullptr, &prepopulated_turls, &local_turls, |
| nullptr, nullptr); |
| ASSERT_EQ(local_turls.size(), 1U); |
| EXPECT_TRUE(local_turls[0]->created_from_play_api()); |
| EXPECT_EQ(local_turls[0]->prepopulate_id(), 0); |
| } |
| |
| // Tests that user modified fields are preserved and overwritten appropriately |
| // in MergeIntoEngineData(). |
| TEST(TemplateURLServiceUtilTest, MergeIntoEngineData) { |
| std::unique_ptr<TemplateURLData> original_turl_data = |
| CreatePrepopulateTemplateURLData(1, "google"); |
| std::unique_ptr<TemplateURLData> url_to_update = |
| CreatePrepopulateTemplateURLData(1, "google"); |
| |
| // Modify the keyword and title for original_turl and set safe_for_autoreplace |
| // to false to simulate a "user edited" template url. |
| original_turl_data->SetShortName(u"modified name"); |
| original_turl_data->SetKeyword(u"new keyword"); |
| original_turl_data->safe_for_autoreplace = false; |
| |
| std::unique_ptr<TemplateURL> original_turl = |
| std::make_unique<TemplateURL>(*original_turl_data); |
| |
| // Set `merge_options` to kOverwriteUserEdits. This should NOT preserve the |
| // modified fields. `url_to_update` should keep the default keyword and name |
| // values as well as safe_for_autoreplace being true. |
| MergeIntoEngineData(original_turl.get(), url_to_update.get(), |
| TemplateURLMergeOption::kOverwriteUserEdits); |
| |
| EXPECT_TRUE(url_to_update->safe_for_autoreplace); |
| EXPECT_EQ(url_to_update->short_name(), u"Search engine name"); |
| EXPECT_EQ(url_to_update->keyword(), u"google"); |
| |
| // Set `merge_options` to kDefault. This should preserve the modified |
| // keyword and title fields from original_turl and update url_to_update |
| // accordingly. |
| MergeIntoEngineData(original_turl.get(), url_to_update.get(), |
| TemplateURLMergeOption::kDefault); |
| |
| EXPECT_FALSE(url_to_update->safe_for_autoreplace); |
| EXPECT_EQ(url_to_update->short_name(), u"modified name"); |
| EXPECT_EQ(url_to_update->keyword(), u"new keyword"); |
| } |
| |
| class TemplateURLServiceUtilLoadTest : public testing::Test { |
| public: |
| // Type used both as input and output of test helpers, to represent the |
| // state of the database from its metadata. |
| struct KeywordTestMetadata { |
| // Version of the built-in keywords data. |
| int data_version = 0; |
| |
| // Chrome milestone. |
| int milestone = 0; |
| |
| // Country stored in the database. As such, when passed as input, it will |
| // be used to update only the database. To change the profile's country, |
| // write directly to prefs. |
| int country = 0; |
| |
| // Number of keywords search engines available. Ignored when passing the |
| // struct as input to set the database's initial state. |
| size_t keyword_engines_count = 0; |
| |
| // Whether the database is expected to be configured to show the extended |
| // list with more than 5 keywords search engines. Gets set in prefs, not |
| // in the database metadata. |
| std::optional<bool> use_extended_list = std::nullopt; |
| |
| // Formatter method for Google Test. |
| friend std::ostream& operator<<(std::ostream& out, |
| const KeywordTestMetadata& m) { |
| return out << "{data_version=" << m.data_version |
| << ", milestone=" << m.milestone << ", country=" << m.country |
| << ", keyword_engines_count=" << m.keyword_engines_count |
| << ", use_extended_list=" |
| << (m.use_extended_list.has_value() |
| ? (*m.use_extended_list ? "yes" : "no") |
| : "unset") |
| << "}"; |
| } |
| |
| // Needed to be able to use EXPECT_EQ with this struct. |
| bool operator==(const KeywordTestMetadata& rhs) const { |
| return data_version == rhs.data_version && milestone == rhs.milestone && |
| country == rhs.country && |
| keyword_engines_count == rhs.keyword_engines_count && |
| use_extended_list == rhs.use_extended_list; |
| } |
| }; |
| |
| const int kCurrentDataVersion = |
| TemplateURLPrepopulateData::kCurrentDataVersion; |
| const int kCurrentMilestone = version_info::GetMajorVersionNumberAsInt(); |
| |
| // For country samples, using Belgium and France for EEA, and the United |
| // States for non-EEA. |
| const int kEeaCountryId = country_codes::CountryStringToCountryID("BE"); |
| const int kOtherEeaCountryId = country_codes::CountryStringToCountryID("FR"); |
| const int kNonEeaCountryId = country_codes::CountryStringToCountryID("US"); |
| |
| TemplateURLServiceUtilLoadTest() { |
| TemplateURLPrepopulateData::RegisterProfilePrefs(prefs_.registry()); |
| TemplateURLService::RegisterProfilePrefs(prefs_.registry()); |
| search_engine_choice_service_ = |
| std::make_unique<search_engines::SearchEngineChoiceService>(prefs_); |
| } |
| |
| // Simulates how the search providers are loaded during Chrome init by |
| // calling `GetSearchProvidersUsingLoadedEngines()`. |
| // The `initial_state` struct represents the state of the database from its |
| // metadata, before the search providers are loaded. Note: |
| // `keyword_engines_count` is ignored in the input. |
| // The returned struct represents the database state after the search |
| // providers are loaded. |
| KeywordTestMetadata SimulateFromDatabaseState( |
| KeywordTestMetadata initial_state) { |
| if (initial_state.use_extended_list.has_value()) { |
| prefs().SetBoolean(prefs::kDefaultSearchProviderKeywordsUseExtendedList, |
| *initial_state.use_extended_list); |
| } else { |
| prefs().ClearPref(prefs::kDefaultSearchProviderKeywordsUseExtendedList); |
| } |
| |
| TemplateURLService::OwnedTemplateURLVector template_urls; |
| WDKeywordsResult::Metadata resource_metadata; |
| resource_metadata.builtin_keyword_data_version = initial_state.data_version; |
| resource_metadata.builtin_keyword_milestone = initial_state.milestone; |
| resource_metadata.builtin_keyword_country = initial_state.country; |
| CallGetSearchProvidersUsingLoadedEngines( |
| &prefs_, search_engine_choice_service_.get(), &template_urls, |
| resource_metadata); |
| |
| std::optional<bool> use_extended_list_output = |
| prefs().HasPrefPath( |
| prefs::kDefaultSearchProviderKeywordsUseExtendedList) |
| ? std::optional<bool>(prefs().GetBoolean( |
| prefs::kDefaultSearchProviderKeywordsUseExtendedList)) |
| : std::nullopt; |
| size_t keyword_engines_count = |
| template_urls.size() - |
| TemplateURLStarterPackData::GetStarterPackEngines().size(); |
| |
| return {.data_version = resource_metadata.builtin_keyword_data_version, |
| .milestone = resource_metadata.builtin_keyword_milestone, |
| .country = resource_metadata.builtin_keyword_country, |
| .keyword_engines_count = keyword_engines_count, |
| .use_extended_list = use_extended_list_output}; |
| } |
| |
| PrefService& prefs() { return prefs_; } |
| |
| private: |
| sync_preferences::TestingPrefServiceSyncable prefs_; |
| std::unique_ptr<search_engines::SearchEngineChoiceService> |
| search_engine_choice_service_; |
| }; |
| |
| TEST_F(TemplateURLServiceUtilLoadTest, |
| GetSearchProvidersUsingLoadedEngines_featureOff) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndDisableFeature(switches::kSearchEngineChoiceTrigger); |
| prefs().SetInteger(country_codes::kCountryIDAtInstall, kEeaCountryId); |
| |
| const KeywordTestMetadata kDefaultUpdatedState = { |
| .data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone, |
| .country = kEeaCountryId, |
| .keyword_engines_count = 5u}; |
| const KeywordTestMetadata kNoUpdate = {.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u}; |
| |
| // Initial state: nothing. Simulates a fresh install. |
| // The function should populate the profile with 5 engines and current |
| // metadata. |
| auto output = SimulateFromDatabaseState({}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // When using the latest metadata from the binary, the function should not |
| // update anything. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone, |
| .country = kEeaCountryId}); |
| EXPECT_EQ(output, (KeywordTestMetadata{.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u})); |
| |
| // Missing country ID and milestone don't trigger an update either. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion}); |
| EXPECT_EQ(output, kNoUpdate); |
| |
| // Out of date keyword data versions trigger updates |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion - 1}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // Country changes trigger updates |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion, .country = kOtherEeaCountryId}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // Milestone changes do NOT trigger updates |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone - 1}); |
| EXPECT_EQ(output, kNoUpdate); |
| |
| // If the extended list was previously used, the function will re-run to |
| // shorten it. |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion, .use_extended_list = true}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // If database's data version is more recent than the one built-in to the |
| // client, the updates are suppressed, including shortening the list. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion + 1, |
| .country = kOtherEeaCountryId, |
| .use_extended_list = true}); |
| EXPECT_EQ(output, (KeywordTestMetadata{.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u, |
| .use_extended_list = true})); |
| } |
| |
| TEST_F(TemplateURLServiceUtilLoadTest, |
| GetSearchProvidersUsingLoadedEngines_featureOnOutOfEea) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndDisableFeature(switches::kSearchEngineChoiceTrigger); |
| prefs().SetInteger(country_codes::kCountryIDAtInstall, kNonEeaCountryId); |
| |
| const KeywordTestMetadata kDefaultUpdatedState = { |
| .data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone, |
| .country = kNonEeaCountryId, |
| .keyword_engines_count = 5u}; |
| const KeywordTestMetadata kNoUpdate = {.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u}; |
| |
| // Initial state: nothing. Simulates a fresh install. |
| // The function should populate the profile with 5 engines and current |
| // metadata. |
| auto output = SimulateFromDatabaseState({}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // When using the latest metadata from the binary, the function should not |
| // update anything. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone, |
| .country = kNonEeaCountryId}); |
| EXPECT_EQ(output, (KeywordTestMetadata{.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u})); |
| |
| // Missing country ID and milestone don't trigger an update either. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion}); |
| EXPECT_EQ(output, kNoUpdate); |
| |
| // Out of date keyword data versions trigger updates |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion - 1}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // Country changes trigger updates |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion, .country = kOtherEeaCountryId}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // Milestone changes do NOT trigger updates |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone - 1}); |
| EXPECT_EQ(output, kNoUpdate); |
| |
| // If the extended list was previously used, the function will re-run to |
| // shorten it. |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion, .use_extended_list = true}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // If database's data version is more recent than the one built-in to the |
| // client, the updates are suppressed, including shortening the list. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion + 1, |
| .country = kOtherEeaCountryId, |
| .use_extended_list = true}); |
| EXPECT_EQ(output, (KeywordTestMetadata{.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u, |
| .use_extended_list = true})); |
| } |
| |
| TEST_F(TemplateURLServiceUtilLoadTest, |
| GetSearchProvidersUsingLoadedEngines_featureOnInEea) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kSearchEngineChoiceTrigger}; |
| prefs().SetInteger(country_codes::kCountryIDAtInstall, kEeaCountryId); |
| const size_t kEeaKeywordEnginesCount = |
| TemplateURLPrepopulateData::GetPrepopulationSetFromCountryIDForTesting( |
| kEeaCountryId) |
| .size(); |
| |
| const KeywordTestMetadata kDefaultUpdatedState = { |
| .data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone, |
| .country = kEeaCountryId, |
| .keyword_engines_count = kEeaKeywordEnginesCount, |
| .use_extended_list = true}; |
| const KeywordTestMetadata kNoUpdate = {.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u, |
| .use_extended_list = true}; |
| |
| // Initial state: nothing. Simulates a fresh install. |
| // The function should populate the profile with 8 engines and current |
| // metadata. |
| auto output = SimulateFromDatabaseState({}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // When using the latest metadata from the binary, the function should not |
| // update anything. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone, |
| .country = kEeaCountryId, |
| .use_extended_list = true}); |
| EXPECT_EQ(output, kNoUpdate); |
| |
| // Missing country ID and milestone don't trigger an update either. |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion, .use_extended_list = true}); |
| EXPECT_EQ(output, kNoUpdate); |
| |
| // Out of date keyword data versions trigger updates |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion - 1, .use_extended_list = true}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // Country changes trigger updates |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .country = kOtherEeaCountryId, |
| .use_extended_list = true}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // Milestone changes trigger updates |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion, |
| .milestone = kCurrentMilestone - 1, |
| .use_extended_list = true}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // If the short list was previously used, the function will re-run to |
| // extend it. |
| output = SimulateFromDatabaseState( |
| {.data_version = kCurrentDataVersion, .use_extended_list = std::nullopt}); |
| EXPECT_EQ(output, kDefaultUpdatedState); |
| |
| // If database's data version is more recent than the one built-in to the |
| // client, the updates are suppressed, including extending the list. |
| output = SimulateFromDatabaseState({.data_version = kCurrentDataVersion + 1, |
| .country = kOtherEeaCountryId, |
| .use_extended_list = std::nullopt}); |
| EXPECT_EQ(output, (KeywordTestMetadata{.data_version = 0, |
| .milestone = 0, |
| .country = 0, |
| .keyword_engines_count = 0u, |
| .use_extended_list = std::nullopt})); |
| } |