chromium/chrome/browser/ash/locale/locale_change_guard_unittest.cc

// 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.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/browser/ash/locale/locale_change_guard.h"

#include <stddef.h>
#include <string.h>

#include "base/containers/fixed_flat_set.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"

namespace ash {

namespace {

// These languages require user notification when locale is automatically
// switched between different regions within the same language.
constexpr auto kShowNotificationLanguages =
    base::MakeFixedFlatSet<std::string_view>({
        "af",   // Afrikaans
        "ak",   // Twi
        "am",   // Amharic
        "an",   // Aragonese
        "ar",   // Arabic
        "as",   // Assamese
        "ast",  // Asturian
        "ay",   // Aymara
        "az",   // Azerbaijani
        "be",   // Belarusian
        "bg",   // Bulgarian
        "bh",   // Bihari
        "bho",  // Bhojpuri
        "bm",   // Bambara
        "bn",   // Bengali
        "br",   // Breton
        "bs",   // Bosnian
        "ca",   // Catalan
        "ceb",  // Cebuano
        "chr",  // Cherokee
        "ckb",  // Sorani (Kurdish-Arabic)
        "co",   // Corsican
        "cs",   // Czech
        "cy",   // Welsh
        "da",   // Danish
        "doi",  // Dogri
        "dv",   // Dhivehi
        "ee",   // Ewe
        "el",   // Greek
        "eo",   // Esperanto
        "es",   // Spanish
        "et",   // Estonian
        "eu",   // Basque
        "fa",   // Persian
        "fi",   // Finnish
        "fil",  // Filipino
        "fo",   // Faroese
        "fy",   // Frisian
        "ga",   // Irish
        "gd",   // Scots Gaelic
        "gl",   // Galician
        "gn",   // Guarani
        "gu",   // Gujarati
        "ha",   // Hausa
        "haw",  // Hawaiian
        "he",   // Hebrew
        "hi",   // Hindi
        "hmn",  // Hmong
        "hr",   // Croatian
        "ht",   // Haitian Creole
        "hu",   // Hungarian
        "hy",   // Armenian
        "ia",   // Interlingua
        "id",   // Indonesian
        "ig",   // Igbo
        "ilo",  // Ilocano
        "is",   // Icelandic
        "ja",   // Japanese
        "jv",   // Javanese
        "ka",   // Georgian
        "kk",   // Kazakh
        "km",   // Cambodian
        "kn",   // Kannada
        "ko",   // Korean
        "kok",  // Konkani
        "kri",  // Krio
        "ku",   // Kurdish
        "ky",   // Kyrgyz
        "la",   // Latin
        "lb",   // Luxembourgish
        "lg",   // Luganda
        "ln",   // Lingala
        "lo",   // Laothian
        "lt",   // Lithuanian
        "lus",  // Mizo
        "lv",   // Latvian
        "mai",  // Maithili
        "mg",   // Malagasy
        "mi",   // Maori
        "mk",   // Macedonian
        "ml",   // Malayalam
        "mn",   // Mongolian
        "mni",  // Manipuri (Meitei Mayek)
        "mo",   // Moldavian
        "mr",   // Marathi
        "ms",   // Malay
        "mt",   // Maltese
        "my",   // Burmese
        "nb",   // Norwegian (Bokmal)
        "ne",   // Nepali
        "nl",   // Dutch
        "nn",   // Norwegian (Nynorsk)
        "no",   // Norwegian
        "nso",  // Sepedi
        "ny",   // Nyanja
        "oc",   // Occitan
        "om",   // Oromo
        "or",   // Oriya
        "pa",   // Punjabi
        "pl",   // Polish
        "ps",   // Pashto
        "pt",   // Portuguese
        "qu",   // Quechua
        "rm",   // Romansh
        "ro",   // Romanian
        "ru",   // Russian
        "rw",   // Kinyarwanda
        "sa",   // Sanskrit
        "sd",   // Sindhi
        "sh",   // Serbo-Croatian
        "si",   // Sinhalese
        "sk",   // Slovak
        "sl",   // Slovenian
        "sm",   // Samoan
        "sn",   // Shona
        "so",   // Somali
        "sq",   // Albanian
        "sr",   // Serbian
        "st",   // Sesotho
        "su",   // Sundanese
        "sv",   // Swedish
        "sw",   // Swahili
        "ta",   // Tamil
        "te",   // Telugu
        "tg",   // Tajik
        "th",   // Thai
        "ti",   // Tigrinya
        "tk",   // Turkmen
        "tn",   // Tswana
        "to",   // Tonga
        "tr",   // Turkish
        "ts",   // Tsonga
        "tt",   // Tatar
        "tw",   // Twi
        "ug",   // Uighur
        "uk",   // Ukrainian
        "ur",   // Urdu
        "uz",   // Uzbek
        "vi",   // Vietnamese
        "wa",   // Walloon
        "wo",   // Wolof
        "xh",   // Xhosa
        "yi",   // Yiddish
        "yo",   // Yoruba
        "zh",   // Chinese
        "zu",   // Zulu
    });

}  // namespace

TEST(LocaleChangeGuardTest, ShowNotificationLocaleChanged) {
  // "en" is used as "global default" in many places.
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en", "it"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("it", "en"));

  // Between two latin locales.
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("fr", "it"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("it", "fr"));

  // en <-> non-latin locale
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en", "zh"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("zh", "en"));

  // latin <-> non-latin locale
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("fr", "zh"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("zh", "fr"));

  // same language
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en", "en"));
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("fr", "fr"));
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("zh", "zh"));
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en", "en-US"));
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en-GB", "en-US"));

  // Different regions within the same language
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en", "en-au"));
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en-AU", "en"));
  EXPECT_FALSE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("en-AU", "en-GB"));

  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("zh", "zh-CN"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("zh-CN", "zh-TW"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("es", "es-419"));
  EXPECT_TRUE(
      LocaleChangeGuard::ShouldShowLocaleChangeNotification("es", "es-ES"));
}

TEST(LocaleChangeGuardTest, ShowNotificationLocaleChangedList) {
  for (std::string_view locale : l10n_util::GetAcceptLanguageListForTesting()) {
    const std::string language = std::string(locale, 0, locale.find('-'));

    const bool notification_allowed =
        kShowNotificationLanguages.contains(language);

    const char* const* skipped_begin =
        LocaleChangeGuard::GetSkipShowNotificationLanguagesForTesting();
    const char* const* skipped_end =
        skipped_begin +
        LocaleChangeGuard::GetSkipShowNotificationLanguagesSizeForTesting();
    const bool notification_skipped =
        (std::find(skipped_begin, skipped_end, language) != skipped_end);

    EXPECT_TRUE(notification_allowed ^ notification_skipped)
        << "Language '" << language << "' (from locale '" << locale
        << "') must be in exactly one list: either "
           "kSkipShowNotificationLanguages (found=" << notification_skipped
        << ") or kShowNotificationLanguages (found=" << notification_allowed
        << ").";
  }
}

}  // namespace ash