| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/translate/core/browser/translate_manager.h" | 5 #include "components/translate/core/browser/translate_manager.h" |
| 6 | 6 |
| 7 #include "base/json/json_reader.h" |
| 7 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
| 8 #include "base/test/histogram_tester.h" | 9 #include "base/test/histogram_tester.h" |
| 10 #include "base/test/scoped_feature_list.h" |
| 9 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 10 #include "components/infobars/core/infobar.h" | 12 #include "components/infobars/core/infobar.h" |
| 11 #include "components/pref_registry/pref_registry_syncable.h" | 13 #include "components/pref_registry/pref_registry_syncable.h" |
| 12 #include "components/pref_registry/testing_pref_service_syncable.h" | 14 #include "components/pref_registry/testing_pref_service_syncable.h" |
| 13 #include "components/translate/core/browser/mock_translate_driver.h" | 15 #include "components/translate/core/browser/mock_translate_driver.h" |
| 14 #include "components/translate/core/browser/translate_browser_metrics.h" | 16 #include "components/translate/core/browser/translate_browser_metrics.h" |
| 15 #include "components/translate/core/browser/translate_client.h" | 17 #include "components/translate/core/browser/translate_client.h" |
| 16 #include "components/translate/core/browser/translate_download_manager.h" | 18 #include "components/translate/core/browser/translate_download_manager.h" |
| 17 #include "components/translate/core/browser/translate_prefs.h" | 19 #include "components/translate/core/browser/translate_prefs.h" |
| 18 #include "components/translate/core/common/translate_pref_names.h" | 20 #include "components/translate/core/common/translate_pref_names.h" |
| 21 #include "components/variations/variations_associated_data.h" |
| 19 #include "net/base/network_change_notifier.h" | 22 #include "net/base/network_change_notifier.h" |
| 20 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 25 |
| 26 using testing::_; |
| 27 using testing::Return; |
| 28 using testing::SetArgPointee; |
| 29 |
| 23 namespace translate { | 30 namespace translate { |
| 24 | 31 |
| 25 namespace { | 32 namespace { |
| 26 | 33 |
| 34 const char kTrialName[] = "MyTrial"; |
| 35 |
| 27 #if defined(OS_CHROMEOS) | 36 #if defined(OS_CHROMEOS) |
| 28 const char kLanguagePreferredLanguages[] = | 37 const char kLanguagePreferredLanguages[] = |
| 29 "settings.language.preferred_languages"; | 38 "settings.language.preferred_languages"; |
| 30 #else | 39 #else |
| 31 const char* kLanguagePreferredLanguages = nullptr; | 40 const char* kLanguagePreferredLanguages = nullptr; |
| 32 #endif | 41 #endif |
| 33 const char kAcceptLanguages[] = "intl.accept_languages"; | 42 const char kAcceptLanguages[] = "intl.accept_languages"; |
| 34 | 43 |
| 35 // Overrides NetworkChangeNotifier, simulatng connection type changes for tests. | 44 // Overrides NetworkChangeNotifier, simulatng connection type changes for tests. |
| 36 // TODO(groby): Combine with similar code in ResourceRequestAllowedNotifierTest. | 45 // TODO(groby): Combine with similar code in ResourceRequestAllowedNotifierTest. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 117 |
| 109 MOCK_METHOD1(IsTranslatableURL, bool(const GURL&)); | 118 MOCK_METHOD1(IsTranslatableURL, bool(const GURL&)); |
| 110 MOCK_METHOD1(ShowReportLanguageDetectionErrorUI, | 119 MOCK_METHOD1(ShowReportLanguageDetectionErrorUI, |
| 111 void(const GURL& report_url)); | 120 void(const GURL& report_url)); |
| 112 | 121 |
| 113 private: | 122 private: |
| 114 TranslateDriver* driver_; | 123 TranslateDriver* driver_; |
| 115 PrefService* prefs_; | 124 PrefService* prefs_; |
| 116 }; | 125 }; |
| 117 | 126 |
| 127 } // namespace |
| 128 |
| 129 namespace testing { |
| 130 |
| 118 class TranslateManagerTest : public ::testing::Test { | 131 class TranslateManagerTest : public ::testing::Test { |
| 119 protected: | 132 protected: |
| 120 TranslateManagerTest() | 133 TranslateManagerTest() |
| 121 : translate_prefs_(&prefs_, | 134 : translate_prefs_(&prefs_, |
| 122 kAcceptLanguages, | 135 kAcceptLanguages, |
| 123 kLanguagePreferredLanguages), | 136 kLanguagePreferredLanguages), |
| 124 manager_(TranslateDownloadManager::GetInstance()), | 137 manager_(TranslateDownloadManager::GetInstance()), |
| 125 mock_translate_client_(&driver_, &prefs_) {} | 138 mock_translate_client_(&driver_, &prefs_), |
| 139 field_trial_list_(new base::FieldTrialList(nullptr)) {} |
| 126 | 140 |
| 127 void SetUp() override { | 141 void SetUp() override { |
| 128 // Ensure we're not requesting a server-side translate language list. | 142 // Ensure we're not requesting a server-side translate language list. |
| 129 TranslateLanguageList::DisableUpdate(); | 143 TranslateLanguageList::DisableUpdate(); |
| 130 prefs_.registry()->RegisterStringPref(kAcceptLanguages, std::string()); | 144 prefs_.registry()->RegisterStringPref(kAcceptLanguages, std::string()); |
| 131 #if defined(OS_CHROMEOS) | 145 #if defined(OS_CHROMEOS) |
| 132 prefs_.registry()->RegisterStringPref(kLanguagePreferredLanguages, | 146 prefs_.registry()->RegisterStringPref(kLanguagePreferredLanguages, |
| 133 std::string()); | 147 std::string()); |
| 134 #endif | 148 #endif |
| 135 TranslatePrefs::RegisterProfilePrefs(prefs_.registry()); | 149 TranslatePrefs::RegisterProfilePrefs(prefs_.registry()); |
| 136 // TODO(groby): Figure out RegisterProfilePrefs() should register this. | 150 // TODO(groby): Figure out RegisterProfilePrefs() should register this. |
| 137 prefs_.registry()->RegisterBooleanPref( | 151 prefs_.registry()->RegisterBooleanPref( |
| 138 prefs::kEnableTranslate, true, | 152 prefs::kEnableTranslate, true, |
| 139 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | 153 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| 140 manager_->ResetForTesting(); | 154 manager_->ResetForTesting(); |
| 141 } | 155 } |
| 156 |
| 157 void TearDown() override { |
| 158 manager_->ResetForTesting(); |
| 159 variations::testing::ClearAllVariationParams(); |
| 160 } |
| 161 |
| 162 // Utility function to prepare translate_manager_ for testing. |
| 163 void PrepareTranslateManager() { |
| 164 TranslateManager::SetIgnoreMissingKeyForTesting(true); |
| 165 translate_manager_.reset(new translate::TranslateManager( |
| 166 &mock_translate_client_, kAcceptLanguages)); |
| 167 } |
| 168 |
| 169 // Prepare the test for ULP related tests. |
| 170 // Put the ulp json into profile. |
| 171 void PrepareULPTest(const char* ulp_json, bool turn_on_feature) { |
| 172 PrepareTranslateManager(); |
| 173 std::unique_ptr<base::Value> profile(CreateProfileFromJSON(ulp_json)); |
| 174 prefs_.SetUserPref(TranslatePrefs::kPrefLanguageProfile, profile.release()); |
| 175 if (turn_on_feature) |
| 176 TurnOnTranslateByULP(); |
| 177 } |
| 178 |
| 179 std::unique_ptr<base::Value> CreateProfileFromJSON(const char* json) { |
| 180 int error_code = 0; |
| 181 std::string error_msg; |
| 182 int error_line = 0; |
| 183 int error_column = 0; |
| 184 |
| 185 std::unique_ptr<base::Value> profile(base::JSONReader::ReadAndReturnError( |
| 186 json, 0, &error_code, &error_msg, &error_line, &error_column)); |
| 187 |
| 188 EXPECT_EQ(0, error_code) << error_msg << " at " << error_line << ":" |
| 189 << error_column << std::endl |
| 190 << json; |
| 191 return profile; |
| 192 } |
| 193 |
| 194 void TurnOnTranslateByULP() { |
| 195 scoped_refptr<base::FieldTrial> trial( |
| 196 CreateFieldTrial(kTrialName, 100, "Enabled", NULL)); |
| 197 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 198 feature_list->RegisterFieldTrialOverride( |
| 199 translate::kTranslateLanguageByULP.name, |
| 200 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get()); |
| 201 scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); |
| 202 } |
| 203 |
| 204 scoped_refptr<base::FieldTrial> CreateFieldTrial( |
| 205 const std::string& trial_name, |
| 206 int total_probability, |
| 207 const std::string& default_group_name, |
| 208 int* default_group_number) { |
| 209 return base::FieldTrialList::FactoryGetFieldTrial( |
| 210 trial_name, total_probability, default_group_name, |
| 211 base::FieldTrialList::kNoExpirationYear, 1, 1, |
| 212 base::FieldTrial::SESSION_RANDOMIZED, default_group_number); |
| 213 } |
| 214 |
| 215 // Functions to help TEST_F in subclass to access private functions in |
| 216 // TranslteManager so we can unit test them. |
| 217 std::string CallGetTargetLanguageFromULP() { |
| 218 return TranslateManager::GetTargetLanguageFromULP(&translate_prefs_); |
| 219 } |
| 220 bool CallLanguageInULP(const std::string& language) { |
| 221 return translate_manager_->LanguageInULP(language); |
| 222 } |
| 223 |
| 142 user_prefs::TestingPrefServiceSyncable prefs_; | 224 user_prefs::TestingPrefServiceSyncable prefs_; |
| 143 | 225 |
| 144 // TODO(groby): request TranslatePrefs from |mock_translate_client_| instead. | 226 // TODO(groby): request TranslatePrefs from |mock_translate_client_| instead. |
| 145 TranslatePrefs translate_prefs_; | 227 TranslatePrefs translate_prefs_; |
| 146 TranslateDownloadManager* manager_; | 228 TranslateDownloadManager* manager_; |
| 147 | 229 |
| 148 TestNetworkChangeNotifier network_notifier_; | 230 TestNetworkChangeNotifier network_notifier_; |
| 149 translate::testing::MockTranslateDriver driver_; | 231 translate::testing::MockTranslateDriver driver_; |
| 150 ::testing::NiceMock<MockTranslateClient> mock_translate_client_; | 232 ::testing::NiceMock<MockTranslateClient> mock_translate_client_; |
| 151 std::unique_ptr<TranslateManager> translate_manager_; | 233 std::unique_ptr<TranslateManager> translate_manager_; |
| 152 | 234 std::unique_ptr<base::FieldTrialList> field_trial_list_; |
| 153 void TearDown() override { manager_->ResetForTesting(); } | 235 base::test::ScopedFeatureList scoped_feature_list_; |
| 154 }; | 236 }; |
| 155 | 237 |
| 156 } // namespace | |
| 157 | 238 |
| 158 // Target language comes from application locale if the locale's language | 239 // Target language comes from application locale if the locale's language |
| 159 // is supported. | 240 // is supported. |
| 160 TEST_F(TranslateManagerTest, GetTargetLanguageDefaultsToAppLocale) { | 241 TEST_F(TranslateManagerTest, GetTargetLanguageDefaultsToAppLocale) { |
| 161 // Ensure the locale is set to a supported language. | 242 // Ensure the locale is set to a supported language. |
| 162 ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("en")); | 243 ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("en")); |
| 163 manager_->set_application_locale("en"); | 244 manager_->set_application_locale("en"); |
| 164 EXPECT_EQ("en", TranslateManager::GetTargetLanguage(&translate_prefs_)); | 245 EXPECT_EQ("en", TranslateManager::GetTargetLanguage(&translate_prefs_)); |
| 165 | 246 |
| 166 // Try a second supported language. | 247 // Try a second supported language. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 | 299 |
| 219 // In the online case, InitiateTranslation will proceed past early out tests. | 300 // In the online case, InitiateTranslation will proceed past early out tests. |
| 220 network_notifier_.SimulateOnline(); | 301 network_notifier_.SimulateOnline(); |
| 221 translate_manager_->InitiateTranslation("de"); | 302 translate_manager_->InitiateTranslation("de"); |
| 222 histogram_tester.ExpectUniqueSample( | 303 histogram_tester.ExpectUniqueSample( |
| 223 kMetricName, | 304 kMetricName, |
| 224 translate::TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_PREFS, | 305 translate::TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_PREFS, |
| 225 1); | 306 1); |
| 226 } | 307 } |
| 227 | 308 |
| 309 // Utility function to set the threshold params |
| 310 void ChangeThresholdInParams( |
| 311 const char* initiate_translation_confidence_threshold, |
| 312 const char* initiate_translation_probability_threshold, |
| 313 const char* target_language_confidence_threshold, |
| 314 const char* target_language_probability_threshold) { |
| 315 ASSERT_TRUE(variations::AssociateVariationParams( |
| 316 kTrialName, "Enabled", {{"initiate_translation_ulp_confidence_threshold", |
| 317 initiate_translation_confidence_threshold}, |
| 318 {"initiate_translation_ulp_probability_threshold", |
| 319 initiate_translation_probability_threshold}, |
| 320 {"target_language_ulp_confidence_threshold", |
| 321 target_language_confidence_threshold}, |
| 322 {"target_language_ulp_probability_threshold", |
| 323 target_language_probability_threshold}})); |
| 324 } |
| 325 |
| 326 // Normal ULP in Json |
| 327 const char ulp_1[] = |
| 328 "{\n" |
| 329 " \"reading\": {\n" |
| 330 " \"confidence\": 0.8,\n" |
| 331 " \"preference\": [\n" |
| 332 " {\n" |
| 333 " \"language\": \"fr\",\n" |
| 334 " \"probability\": 0.6\n" |
| 335 " }, {\n" |
| 336 " \"language\": \"pt-PT\",\n" |
| 337 " \"probability\": 0.4\n" |
| 338 " }\n" |
| 339 " ]\n" |
| 340 " }\n" |
| 341 "}"; |
| 342 |
| 343 // ULP in Json with smaller probability of several es-* language codes |
| 344 // sum up to 0.7. |
| 345 const char ulp_2[] = |
| 346 "{\n" |
| 347 " \"reading\": {\n" |
| 348 " \"confidence\": 0.9,\n" |
| 349 " \"preference\": [\n" |
| 350 " {\n" |
| 351 " \"language\": \"fr\",\n" |
| 352 " \"probability\": 0.3\n" |
| 353 " }, {\n" |
| 354 " \"language\": \"es-419\",\n" |
| 355 " \"probability\": 0.2\n" |
| 356 " }, {\n" |
| 357 " \"language\": \"es-MX\",\n" |
| 358 " \"probability\": 0.2\n" |
| 359 " }, {\n" |
| 360 " \"language\": \"es-US\",\n" |
| 361 " \"probability\": 0.2\n" |
| 362 " }, {\n" |
| 363 " \"language\": \"es-CL\",\n" |
| 364 " \"probability\": 0.1\n" |
| 365 " }\n" |
| 366 " ]\n" |
| 367 " }\n" |
| 368 "}"; |
| 369 |
| 370 TEST_F(TranslateManagerTest, TestGetTargetLanguageFromULPFeatureOff) { |
| 371 PrepareULPTest(ulp_1, false); |
| 372 |
| 373 EXPECT_STREQ("", CallGetTargetLanguageFromULP().c_str()); |
| 374 } |
| 375 |
| 376 TEST_F(TranslateManagerTest, TestGetTargetLanguageFromULPHighConfidence) { |
| 377 PrepareULPTest(ulp_1, true); |
| 378 |
| 379 // The default hardcoded threshold are confidence: 0.7, probability: 0.55 |
| 380 EXPECT_STREQ("fr", CallGetTargetLanguageFromULP().c_str()); |
| 381 } |
| 382 |
| 383 TEST_F(TranslateManagerTest, |
| 384 TestGetTargetLanguageFromULPHighConfidenceThresholdFromConfig) { |
| 385 PrepareULPTest(ulp_1, true); |
| 386 ChangeThresholdInParams("", "", "0.81", "0.5"); |
| 387 |
| 388 // Should get empty string as result since the confidence threshold is above |
| 389 // the ULP (0.8 in the ulp_1). |
| 390 EXPECT_STREQ("", CallGetTargetLanguageFromULP().c_str()); |
| 391 } |
| 392 |
| 393 TEST_F(TranslateManagerTest, |
| 394 TestGetTargetLanguageFromULPHighProbabilityThresholdFromConfig) { |
| 395 PrepareULPTest(ulp_1, true); |
| 396 ChangeThresholdInParams("", "", "0.4", "0.61"); |
| 397 |
| 398 // Should get empty string as result since the confidence threshold is above |
| 399 // the ULP (0.6 for fr in the ulp_1). |
| 400 EXPECT_STREQ("", CallGetTargetLanguageFromULP().c_str()); |
| 401 } |
| 402 |
| 403 TEST_F(TranslateManagerTest, TestGetTargetLanguageFromULPProbabilitySumUp) { |
| 404 PrepareULPTest(ulp_2, true); |
| 405 ChangeThresholdInParams("", "", "0.4", "0.61"); |
| 406 |
| 407 // Should get "es" since the sum of the "es-*" probability is 0.7. |
| 408 EXPECT_STREQ("es", CallGetTargetLanguageFromULP().c_str()); |
| 409 } |
| 410 |
| 411 TEST_F(TranslateManagerTest, TestLanguageInULPFeatureOff) { |
| 412 PrepareULPTest(ulp_1, false); |
| 413 |
| 414 EXPECT_FALSE(CallLanguageInULP("fr")); |
| 415 EXPECT_FALSE(CallLanguageInULP("pt")); |
| 416 EXPECT_FALSE(CallLanguageInULP("zh-TW")); |
| 417 } |
| 418 |
| 419 TEST_F(TranslateManagerTest, TestLanguageInULPDefaultThreshold) { |
| 420 PrepareULPTest(ulp_1, true); |
| 421 |
| 422 // The default hardcoded threshold are confidence: 0.75, probability: 0.5 |
| 423 EXPECT_TRUE(CallLanguageInULP("fr")); |
| 424 EXPECT_FALSE(CallLanguageInULP("pt")); |
| 425 EXPECT_FALSE(CallLanguageInULP("zh-TW")); |
| 426 } |
| 427 |
| 428 TEST_F(TranslateManagerTest, |
| 429 TestLanguageInULPHighConfidenceThresholdFromConfig) { |
| 430 PrepareULPTest(ulp_1, true); |
| 431 ChangeThresholdInParams("0.9", "0.5", "", ""); |
| 432 // "fr" and "pt" should return false because the confidence threshold is set |
| 433 // to 0.9. |
| 434 EXPECT_FALSE(CallLanguageInULP("fr")); |
| 435 EXPECT_FALSE(CallLanguageInULP("pt")); |
| 436 EXPECT_FALSE(CallLanguageInULP("zh-TW")); |
| 437 } |
| 438 |
| 439 TEST_F(TranslateManagerTest, |
| 440 TestLanguageInULPLowConfidenceThresholdFromConfig) { |
| 441 PrepareULPTest(ulp_1, true); |
| 442 ChangeThresholdInParams("0.79", "0.39", "", ""); |
| 443 // Both "fr" and "pt" should reutrn true because the confidence threshold is |
| 444 // 0.79 and lower than 0.8 and the probability threshold is lower than both |
| 445 // the one with "fr" (0.6) and "pt-PT" (0.4). |
| 446 EXPECT_TRUE(CallLanguageInULP("fr")); |
| 447 EXPECT_TRUE(CallLanguageInULP("pt")); |
| 448 EXPECT_FALSE(CallLanguageInULP("zh-TW")); |
| 449 } |
| 450 |
| 451 } // namespace testing |
| 452 |
| 228 } // namespace translate | 453 } // namespace translate |
| OLD | NEW |