1 #include "common/common_pch.h"
2 
3 #include "common/bcp47.h"
4 
5 #include "tests/unit/init.h"
6 
7 namespace {
8 
9 using namespace mtx::bcp47;
10 
TEST(BCP47LanguageTags,Construction)11 TEST(BCP47LanguageTags, Construction) {
12   EXPECT_FALSE(language_c{}.is_valid());
13 }
14 
TEST(BCP47LanguageTags,ParsingValid)15 TEST(BCP47LanguageTags, ParsingValid) {
16   EXPECT_TRUE(language_c::parse("de-Latn-CH-x-weeee").is_valid());
17   EXPECT_TRUE(language_c::parse("deu-Latn-CH-x-weeee").is_valid());
18   EXPECT_TRUE(language_c::parse("ger-Latn-076-x-weeee").is_valid());
19   EXPECT_TRUE(language_c::parse("x-muh-to-the-kuh").is_valid());
20   EXPECT_TRUE(language_c::parse("ar-aao-Latn-DZ").is_valid());
21   EXPECT_TRUE(language_c::parse("sr-ekavsk").is_valid());
22   EXPECT_TRUE(language_c::parse("sr-Latn-ekavsk").is_valid());
23   EXPECT_TRUE(language_c::parse("sr-Cyrl-ekavsk").is_valid());
24 }
25 
TEST(BCP47LanguageTags,ParsingValidUNM49)26 TEST(BCP47LanguageTags, ParsingValidUNM49) {
27   EXPECT_EQ("es-MX"s,  language_c::parse("es-484").format());
28   EXPECT_EQ("es-419"s, language_c::parse("es-419").format());
29 }
30 
TEST(BCP47LanguageTags,ParsingInvalid)31 TEST(BCP47LanguageTags, ParsingInvalid) {
32   EXPECT_FALSE(language_c::parse("zyx-Latn-CH-x-weeee").is_valid());  // invalid (zyx not ISO 639 code)
33   EXPECT_FALSE(language_c::parse("ger-muku-CH-x-weeee").is_valid());  // invalid (muku not a script)
34   EXPECT_FALSE(language_c::parse("ger-777").is_valid());              // invalid (777 not a region code)
35   EXPECT_FALSE(language_c::parse("zh-min").is_valid());               // invalid (min not allowed with zh)
36   EXPECT_FALSE(language_c::parse("gonzo").is_valid());                // invalid
37   EXPECT_FALSE(language_c::parse("de-aao-Latn-DZ").is_valid());       // invalid (aoo not valid with de)
38   EXPECT_FALSE(language_c::parse("de-ekavsk").is_valid());            // invalid (ekavsk not valid with de)
39   EXPECT_FALSE(language_c::parse("es-0").is_valid());                 // invalid (no such region)
40 }
41 
TEST(BCP47LanguageTags,Formatting)42 TEST(BCP47LanguageTags, Formatting) {
43   EXPECT_EQ(""s, language_c{}.format());
44 
45   language_c l;
46 
47   l.set_valid(true);
48   l.set_language("de");
49   l.set_script("latn");
50   l.set_region("ch");
51   l.set_private_use({ "weee"s });
52 
53   EXPECT_EQ("de-Latn-CH-x-weee"s, l.format());
54   EXPECT_EQ("German (de-Latn-CH-x-weee)"s, l.format_long());
55 
56   l = language_c{};
57   l.set_valid(true);
58   l.set_language("DE");
59   l.set_script("LATN");
60   l.set_region("cH");
61   l.set_private_use({ "WEEE"s });
62 
63   EXPECT_EQ("de-Latn-CH-x-weee"s, l.format());
64   EXPECT_EQ("German (de-Latn-CH-x-weee)"s, l.format_long());
65 
66   l = language_c{};
67   l.set_valid(true);
68   l.set_private_use({ "weee"s, "wooo"s });
69 
70   EXPECT_EQ("x-weee-wooo"s, l.format());
71   EXPECT_EQ("x-weee-wooo"s, l.format_long());
72 
73   l = language_c{};
74   l.set_private_use({ "weee"s, "wooo"s });
75 
76   EXPECT_EQ(""s,            l.format());
77   EXPECT_EQ(""s,            l.format(false));
78   EXPECT_EQ("x-weee-wooo"s, l.format(true));
79 
80   EXPECT_EQ(""s,            l.format_long());
81   EXPECT_EQ(""s,            l.format_long(false));
82   EXPECT_EQ("x-weee-wooo"s, l.format_long(true));
83 
84   l = language_c{};
85   l.set_language("ja");
86   l.add_extension({ "t"s, { "test"s }});
87   l.add_extension({ "u"s, { "attr"s, "co"s, "phonebk"s, "attr"s, "zz"s, "oooqqq"s }});
88   l.set_valid(true);
89 
90   EXPECT_EQ("ja-t-test-u-attr-co-phonebk-attr-zz-oooqqq"s, l.format());
91 }
92 
TEST(BCP47LanguageTags,FormattingInvalidWithoutLanguage)93 TEST(BCP47LanguageTags, FormattingInvalidWithoutLanguage) {
94   auto l = language_c{};
95 
96   l.set_region("FR"s);
97   l.set_private_use({ "moo"s });
98 
99   EXPECT_EQ(""s,          l.format());
100   EXPECT_EQ("-FR-x-moo"s, l.format(true));
101 }
102 
TEST(BCP47LanguageTags,CodeConversion)103 TEST(BCP47LanguageTags, CodeConversion) {
104   EXPECT_EQ(""s,    language_c{}.get_iso639_alpha_3_code());
105   EXPECT_EQ("ger"s, language_c::parse("de").get_iso639_alpha_3_code());
106   EXPECT_EQ("ger"s, language_c::parse("deu").get_iso639_alpha_3_code());
107   EXPECT_EQ("ger"s, language_c::parse("ger").get_iso639_alpha_3_code());
108 
109   language_c l;
110   l.set_language("zyx");
111   EXPECT_EQ(""s, l.get_iso639_alpha_3_code());
112 
113   EXPECT_FALSE(language_c{}.has_valid_iso639_code());
114   EXPECT_FALSE(language_c::parse("zyx").has_valid_iso639_code());
115   EXPECT_FALSE(language_c::parse("x-zyx").has_valid_iso639_code());
116 
117   EXPECT_TRUE(language_c::parse("de").has_valid_iso639_code());
118   EXPECT_TRUE(language_c::parse("deu").has_valid_iso639_code());
119   EXPECT_TRUE(language_c::parse("ger").has_valid_iso639_code());
120 
121   EXPECT_EQ("ger"s, language_c::parse("de").get_iso639_2_alpha_3_code_or("eng"s));
122   EXPECT_EQ("ger"s, language_c::parse("deu").get_iso639_2_alpha_3_code_or("eng"s));
123   EXPECT_EQ("ger"s, language_c::parse("ger").get_iso639_2_alpha_3_code_or("eng"s));
124 
125   EXPECT_EQ("eng"s, language_c::parse("").get_iso639_2_alpha_3_code_or("eng"s));
126   EXPECT_EQ("eng"s, language_c::parse("x-moo").get_iso639_2_alpha_3_code_or("eng"s));
127 }
128 
TEST(BCP47LanguageTags,UnorderedMap)129 TEST(BCP47LanguageTags, UnorderedMap) {
130   std::unordered_map<language_c, int> m;
131 
132   m[language_c::parse("de-Latn")] = 42;
133   EXPECT_EQ(42, m[language_c::parse("de-Latn")]);
134   EXPECT_EQ(0,  m[language_c::parse("de")]);
135 }
136 
TEST(BCP47LanguageTags,Clearing)137 TEST(BCP47LanguageTags, Clearing) {
138   auto l = language_c::parse("eng");
139 
140   ASSERT_TRUE(l.has_valid_iso639_code());
141 
142   l.clear();
143 
144   EXPECT_FALSE(l.is_valid());
145 }
146 
TEST(BCP47LanguageTags,EqualityOperators)147 TEST(BCP47LanguageTags, EqualityOperators) {
148   EXPECT_TRUE(language_c::parse("ger") == language_c::parse("ger"));
149   EXPECT_TRUE(language_c::parse("ger") == language_c::parse("deu"));
150   EXPECT_TRUE(language_c::parse("ger") == language_c::parse("de"));
151 
152   EXPECT_TRUE(language_c::parse("deu") == language_c::parse("ger"));
153   EXPECT_TRUE(language_c::parse("de")  == language_c::parse("ger"));
154 
155   EXPECT_FALSE(language_c::parse("eng") == language_c::parse("ger"));
156   EXPECT_FALSE(language_c::parse("eng") == language_c::parse("deu"));
157   EXPECT_FALSE(language_c::parse("eng") == language_c::parse("de"));
158 
159   EXPECT_FALSE(language_c::parse("ger") == language_c::parse("eng"));
160   EXPECT_FALSE(language_c::parse("deu") == language_c::parse("eng"));
161   EXPECT_FALSE(language_c::parse("de")  == language_c::parse("eng"));
162 
163   EXPECT_FALSE(language_c::parse("ger") != language_c::parse("ger"));
164   EXPECT_FALSE(language_c::parse("ger") != language_c::parse("deu"));
165   EXPECT_FALSE(language_c::parse("ger") != language_c::parse("de"));
166 
167   EXPECT_FALSE(language_c::parse("deu") != language_c::parse("ger"));
168   EXPECT_FALSE(language_c::parse("de")  != language_c::parse("ger"));
169 
170   EXPECT_TRUE(language_c::parse("eng") != language_c::parse("ger"));
171   EXPECT_TRUE(language_c::parse("eng") != language_c::parse("deu"));
172   EXPECT_TRUE(language_c::parse("eng") != language_c::parse("de"));
173 
174   EXPECT_TRUE(language_c::parse("ger") != language_c::parse("eng"));
175   EXPECT_TRUE(language_c::parse("deu") != language_c::parse("eng"));
176   EXPECT_TRUE(language_c::parse("de")  != language_c::parse("eng"));
177 }
178 
TEST(BCP47LanguageTags,DifferenceBetweenISO639_2And639_3)179 TEST(BCP47LanguageTags, DifferenceBetweenISO639_2And639_3) {
180   EXPECT_TRUE(language_c::parse("de").has_valid_iso639_code());
181   EXPECT_TRUE(language_c::parse("de").has_valid_iso639_2_code());
182 
183   EXPECT_TRUE(language_c::parse("cmn").has_valid_iso639_code());
184   EXPECT_FALSE(language_c::parse("cmn").has_valid_iso639_2_code());
185 }
186 
TEST(BCP47LanguageTags,PrefixValidation)187 TEST(BCP47LanguageTags, PrefixValidation) {
188   EXPECT_TRUE(language_c::parse("de-CH-1996").is_valid());
189   EXPECT_TRUE(language_c::parse("sr-Cyrl-ekavsk").is_valid());
190   EXPECT_TRUE(language_c::parse("sr-Cyrl-SR-ekavsk").is_valid());
191   EXPECT_TRUE(language_c::parse("en-GB-scotland").is_valid());
192   EXPECT_TRUE(language_c::parse("zh-Latn-CN-pinyin").is_valid());
193 
194   EXPECT_FALSE(language_c::parse("sr-biske").is_valid());
195   EXPECT_FALSE(language_c::parse("tr-rozaj").is_valid());
196 
197   EXPECT_TRUE(language_c::parse("sl-rozaj").is_valid());
198   EXPECT_TRUE(language_c::parse("sl-rozaj-biske").is_valid());
199   EXPECT_TRUE(language_c::parse("sl-rozaj-1994").is_valid());
200   EXPECT_TRUE(language_c::parse("sl-rozaj-biske-1994").is_valid());
201   EXPECT_FALSE(language_c::parse("sl-1994").is_valid());
202   EXPECT_FALSE(language_c::parse("sl-biske-rozaj").is_valid());
203 
204   EXPECT_TRUE(language_c::parse("de-1901").is_valid());
205   EXPECT_TRUE(language_c::parse("de-1996").is_valid());
206   EXPECT_FALSE(language_c::parse("de-1901-1996").is_valid());
207 
208   EXPECT_TRUE(language_c::parse("zh-cmn").is_valid());
209   EXPECT_TRUE(language_c::parse("zh-yue").is_valid());
210   EXPECT_FALSE(language_c::parse("zh-cmn-yue").is_valid());
211 
212   EXPECT_TRUE(language_c::parse("hy-arevela").is_valid());
213   EXPECT_TRUE(language_c::parse("hy-arevmda").is_valid());
214   EXPECT_FALSE(language_c::parse("hy-arevela-arevmda").is_valid());
215 
216   EXPECT_TRUE(language_c::parse("ja-Latn-hepburn").is_valid());
217   EXPECT_TRUE(language_c::parse("ja-Latn-hepburn-heploc").is_valid());
218   EXPECT_FALSE(language_c::parse("ja-Latn-heploc").is_valid());
219 
220 }
221 
TEST(BCP47LanguageTags,RFC4646AssortedValid)222 TEST(BCP47LanguageTags, RFC4646AssortedValid) {
223   EXPECT_TRUE(language_c::parse("de-1996").is_valid()); // section 3.1
224   EXPECT_TRUE(language_c::parse("de-Latg-1996").is_valid()); // section 3.1
225   EXPECT_TRUE(language_c::parse("de-CH-1996").is_valid()); // section 3.1
226 }
227 
TEST(BCP47LanguageTags,RFC4646AssortedInvalid)228 TEST(BCP47LanguageTags, RFC4646AssortedInvalid) {
229   EXPECT_FALSE(language_c::parse("fr-1996").is_valid()); // section 3.1
230 }
231 
TEST(BCP47LanguageTags,RFC4646AppendixBValid)232 TEST(BCP47LanguageTags, RFC4646AppendixBValid) {
233   // Simple language subtag:
234   EXPECT_TRUE(language_c::parse("de").is_valid()); // (German)
235   EXPECT_TRUE(language_c::parse("fr").is_valid()); // (French)
236   EXPECT_TRUE(language_c::parse("ja").is_valid()); // (Japanese)
237   // [MKVToolNix: deactivated as grandfathered entries are currently not supported]
238   // EXPECT_TRUE(language_c::parse("i-enochian").is_valid()); // (example of a grandfathered tag)
239 
240   // Language subtag plus Script subtag:
241   EXPECT_TRUE(language_c::parse("zh-Hant").is_valid()); // (Chinese written using the Traditional Chinese script)
242   EXPECT_TRUE(language_c::parse("zh-Hans").is_valid()); // (Chinese written using the Simplified Chinese script)
243   EXPECT_TRUE(language_c::parse("sr-Cyrl").is_valid()); // (Serbian written using the Cyrillic script)
244   EXPECT_TRUE(language_c::parse("sr-Latn").is_valid()); // (Serbian written using the Latin script)
245 
246   // Language-Script-Region:
247   EXPECT_TRUE(language_c::parse("zh-Hans-CN").is_valid()); // (Chinese written using the Simplified script as used in mainland China)
248   EXPECT_TRUE(language_c::parse("sr-Latn-SR").is_valid()); // (Serbian written using the Latin script as used in Serbia) [MKVToolNix: original was CS = Serbian & Montenegro, but that country doesn't exist anymore, and neither does the code.]
249 
250   // Language-Variant:
251   EXPECT_TRUE(language_c::parse("sl-rozaj").is_valid()); // (Resian dialect of Slovenian
252   EXPECT_TRUE(language_c::parse("sl-nedis").is_valid()); // (Nadiza dialect of Slovenian)
253 
254   // Language-Region-Variant:
255   EXPECT_TRUE(language_c::parse("de-CH-1901").is_valid()); // (German as used in Switzerland using the 1901 variant [orthography])
256   EXPECT_TRUE(language_c::parse("sl-IT-nedis").is_valid()); // (Slovenian as used in Italy, Nadiza dialect)
257 
258   // Language-Script-Region-Variant:
259   EXPECT_TRUE(language_c::parse("sl-Latn-IT-nedis").is_valid()); // (Nadiza dialect of Slovenian written using the Latin script as used in Italy.  Note that this tag is NOT RECOMMENDED because subtag 'sl' has a Suppress-Script value of 'Latn')
260 
261   // Language-Region:
262   EXPECT_TRUE(language_c::parse("de-DE").is_valid()); // (German for Germany)
263   EXPECT_TRUE(language_c::parse("en-US").is_valid()); // (English as used in the United States)
264   EXPECT_TRUE(language_c::parse("es-419").is_valid()); // (Spanish appropriate for the Latin America and Caribbean region using the UN region code)
265 
266   // Private use subtags:
267   EXPECT_TRUE(language_c::parse("de-CH-x-phonebk").is_valid());
268   EXPECT_TRUE(language_c::parse("az-Arab-x-AZE-derbend").is_valid());
269 
270   // Extended language subtags (examples ONLY: extended languages MUST be defined by revision or update to this document):
271   EXPECT_TRUE(language_c::parse("zh-mnp").is_valid());
272   EXPECT_FALSE(language_c::parse("zh-mnp-nan-Hant-CN").is_valid()); // invalid as 'nan' must only be used with prefix 'zh'
273 
274   // Private use registry values:
275   EXPECT_TRUE(language_c::parse("x-whatever").is_valid()); // (private use using the singleton 'x')
276   EXPECT_TRUE(language_c::parse("qaa-Qaaa-QM-x-southern").is_valid()); // (all private tags)
277   EXPECT_TRUE(language_c::parse("de-Qaaa").is_valid()); // (German, with a private script)
278   EXPECT_TRUE(language_c::parse("sr-Latn-QM").is_valid()); // (Serbian, Latin-script, private region)
279   EXPECT_TRUE(language_c::parse("sr-Qaaa-SR").is_valid()); // (Serbian, private script, for Serbia) [MKVToolNix: original used CS = Sebia & Montenegro, a country that doesn't exist anymore]
280 
281   // Tags that use extensions (examples ONLY: extensions MUST be defined by revision or update to this document or by RFC):
282   // EXPECT_TRUE(language_c::parse("en-US-u-islamCal").is_valid());
283   // EXPECT_TRUE(language_c::parse("zh-CN-a-myExt-x-private").is_valid());
284   // EXPECT_TRUE(language_c::parse("en-a-myExt-b-another").is_valid());
285 }
286 
TEST(BCP47LanguageTags,RFC4646AppendixBInvalid)287 TEST(BCP47LanguageTags, RFC4646AppendixBInvalid) {
288   EXPECT_FALSE(language_c::parse("de-419-DE").is_valid()); // (two region tags)
289   EXPECT_FALSE(language_c::parse("a-DE").is_valid()); // (use of a single-character subtag in primary position; note that there are a few grandfathered tags that start with "i-" that are valid)
290   EXPECT_FALSE(language_c::parse("ar-a-aaa-b-bbb-a-ccc").is_valid()); // (two extensions with same single-letter prefix)
291 }
292 
TEST(BCP47LanguageTags,OnlyCertainScriptsAllowedOrNoScriptAtAll)293 TEST(BCP47LanguageTags, OnlyCertainScriptsAllowedOrNoScriptAtAll) {
294   EXPECT_TRUE(language_c::parse("sr-Bali").is_valid());
295   EXPECT_TRUE(language_c::parse("sr-Cyrl").is_valid());
296   EXPECT_TRUE(language_c::parse("sr-Latn").is_valid());
297 
298   EXPECT_TRUE(language_c::parse("sr-ekavsk").is_valid());
299   EXPECT_TRUE(language_c::parse("sr-Cyrl-ekavsk").is_valid());
300   EXPECT_TRUE(language_c::parse("sr-Latn-ekavsk").is_valid());
301 
302   EXPECT_TRUE(language_c::parse("sr-Latn-RS-ekavsk").is_valid());
303 
304   EXPECT_FALSE(language_c::parse("sr-Bali-ekavsk").is_valid());
305 }
306 
TEST(BCP47LanguageTags,ExtensionsBasics)307 TEST(BCP47LanguageTags, ExtensionsBasics) {
308   EXPECT_TRUE(language_c::parse("ja-t-test").is_valid());
309   EXPECT_TRUE(language_c::parse("ja-t-abcdefgh").is_valid());
310   EXPECT_TRUE(language_c::parse("ja-t-test-u-attr-co-phonebk").is_valid());
311   EXPECT_TRUE(language_c::parse("ja-t-test-u-attr-co-phonebk-attr-zz-oooqqq").is_valid());
312   EXPECT_TRUE(language_c::parse("ja-u-attr-co-phonebk-t-test").is_valid());
313 
314   EXPECT_FALSE(language_c::parse("ja-t").is_valid());                                  // Nothing following the singleton
315   EXPECT_FALSE(language_c::parse("ja-t-u-attr-co-phonebk").is_valid());                // No extension subtag within the t extension
316   EXPECT_FALSE(language_c::parse("ja-t-u-attr-co-phonebk").is_valid());                // No extension subtag within the t extension
317   EXPECT_FALSE(language_c::parse("ja-u-attr-co-phonebk-u-attr-zz-oooqqq").is_valid()); // Singleton occurring multiple times
318   EXPECT_FALSE(language_c::parse("ja-t-z").is_valid());                                // Extension subtag too short
319   EXPECT_FALSE(language_c::parse("ja-t-abcdefghi").is_valid());                        // Extension subtag too long
320 
321   EXPECT_FALSE(language_c::parse("ja-a-moo-cow").is_valid());                          // Singleton a is not registered at the moment
322 }
323 
TEST(BCP47LanguageTags,ExtensionsRFC6067)324 TEST(BCP47LanguageTags, ExtensionsRFC6067) {
325   EXPECT_TRUE(language_c::parse("de-DE-u-attr-co-phonebk").is_valid());
326 }
327 
TEST(BCP47LanguageTags,ExtensionsRFC6497)328 TEST(BCP47LanguageTags, ExtensionsRFC6497) {
329   EXPECT_TRUE(language_c::parse("und-Cyrl-t-und-latn-m0-ungegn-2007").is_valid());
330   EXPECT_TRUE(language_c::parse("und-Hebr-t-und-latn-m0-ungegn-1972").is_valid());
331   EXPECT_TRUE(language_c::parse("ja-t-it-m0-xxx-v21a-2007").is_valid());
332 }
333 
TEST(BCP47LanguageTags,ExtensionsFormatting)334 TEST(BCP47LanguageTags, ExtensionsFormatting) {
335   EXPECT_EQ("ja-t-test-u-attr-co-phonebk"s, language_c::parse("ja-T-Test-U-AttR-CO-phoNEbk").format());
336   EXPECT_EQ("ja-t-test-u-attr-co-phonebk"s, language_c::parse("ja-U-AttR-CO-phoNEbk-T-Test").format());
337 }
338 
TEST(BCP47LanguageTags,Matching)339 TEST(BCP47LanguageTags, Matching) {
340   EXPECT_FALSE(language_c{}                  .matches(language_c{}));
341   EXPECT_FALSE(language_c{}                  .matches(language_c::parse("es")));
342   EXPECT_FALSE(language_c::parse("es")       .matches(language_c{}));
343 
344   EXPECT_TRUE(language_c::parse("es")        .matches(language_c::parse("es")));
345   EXPECT_TRUE(language_c::parse("es-MX")     .matches(language_c::parse("es")));
346   EXPECT_TRUE(language_c::parse("es-Latn-MX").matches(language_c::parse("es")));
347 
348   EXPECT_TRUE(language_c::parse("es-MX")     .matches(language_c::parse("es-MX")));
349   EXPECT_TRUE(language_c::parse("es-Latn-MX").matches(language_c::parse("es-Latn-MX")));
350 
351   EXPECT_TRUE(language_c::parse("es-Latn-MX").matches(language_c::parse("es-MX")));
352 
353   EXPECT_FALSE(language_c::parse("es")       .matches(language_c::parse("es-MX")));
354   EXPECT_FALSE(language_c::parse("es")       .matches(language_c::parse("es-Latn-MX")));
355 }
356 
TEST(BCP47LanguageTags,FindBestMatch)357 TEST(BCP47LanguageTags, FindBestMatch) {
358   using V = std::vector<language_c>;
359 
360   EXPECT_FALSE(language_c{}           .find_best_match({}).is_valid());
361   EXPECT_FALSE(language_c::parse("es").find_best_match({}).is_valid());
362   EXPECT_FALSE(language_c{}           .find_best_match(V{ language_c{} }).is_valid() );
363   EXPECT_FALSE(language_c{}           .find_best_match(V{ language_c::parse("es") }).is_valid() );
364 
365   EXPECT_FALSE(language_c::parse("es")   .find_best_match(V{ language_c::parse("de"),    language_c::parse("fr") }).is_valid());
366   EXPECT_FALSE(language_c::parse("es")   .find_best_match(V{ language_c::parse("es-US"), language_c::parse("es-ES") }).is_valid());
367   EXPECT_FALSE(language_c::parse("es-MX").find_best_match(V{ language_c::parse("es-US"), language_c::parse("es-ES") }).is_valid());
368 
369   EXPECT_EQ(language_c::parse("es"),      language_c::parse("es")        .find_best_match(V{ language_c::parse("es") }));
370   EXPECT_EQ(language_c::parse("es"),      language_c::parse("es")        .find_best_match(V{ language_c::parse("de"),      language_c::parse("es") }));
371   EXPECT_EQ(language_c::parse("es"),      language_c::parse("es-Latn-MX").find_best_match(V{ language_c::parse("de"),      language_c::parse("es"), language_c::parse("fr") }));
372   EXPECT_EQ(language_c::parse("es"),      language_c::parse("es-Latn-MX").find_best_match(V{ language_c::parse("es-US"),   language_c::parse("es"), language_c::parse("es-ES") }));
373   EXPECT_EQ(language_c::parse("es-MX"),   language_c::parse("es-Latn-MX").find_best_match(V{ language_c::parse("es-US"),   language_c::parse("es"), language_c::parse("es-MX") }));
374   EXPECT_EQ(language_c::parse("es-Latn"), language_c::parse("es-Latn-MX").find_best_match(V{ language_c::parse("es-Latn"), language_c::parse("es"), language_c::parse("es-MX") }));
375 }
376 
TEST(BCP47LanguageTags,ISO3166_1_Alpha2Codes)377 TEST(BCP47LanguageTags, ISO3166_1_Alpha2Codes) {
378   EXPECT_FALSE(language_c::parse("es").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
379   EXPECT_FALSE(language_c::parse("es-029").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
380   EXPECT_FALSE(language_c::parse("es-AA").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
381   EXPECT_FALSE(language_c::parse("es-QT").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
382   EXPECT_FALSE(language_c::parse("es-XS").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
383   EXPECT_TRUE(language_c::parse("es-ES").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
384   EXPECT_TRUE(language_c::parse("es-724").has_valid_iso3166_1_alpha_2_or_top_level_domain_country_code());
385 
386   EXPECT_EQ(""s, language_c::parse("es").get_iso3166_1_alpha_2_code());
387   EXPECT_EQ(""s, language_c::parse("es-029").get_iso3166_1_alpha_2_code());
388   EXPECT_EQ("ES"s, language_c::parse("es-ES").get_iso3166_1_alpha_2_code());
389   EXPECT_EQ("ES"s, language_c::parse("es-724").get_iso3166_1_alpha_2_code());
390   EXPECT_EQ("es"s, language_c::parse("es-ES").get_top_level_domain_country_code());
391   EXPECT_EQ("es"s, language_c::parse("es-724").get_top_level_domain_country_code());
392 
393   EXPECT_EQ("GB"s, language_c::parse("en-GB").get_iso3166_1_alpha_2_code());
394   EXPECT_EQ("uk"s, language_c::parse("en-GB").get_top_level_domain_country_code());
395 }
396 
397 }
398