• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "androidfw/LocaleDataLookup.h"
18 
19 #include <cstddef>
20 #include <string>
21 
22 #include "gtest/gtest.h"
23 #include "gmock/gmock.h"
24 
25 
26 namespace android {
27 
28 constexpr const char NULL_SCRIPT[4] = {'\0', '\0', '\0','\0' };
29 
30 #define EXPECT_SCEIPT_EQ(ex, s) EXPECT_EQ(0, s == nullptr ? -1 : memcmp(ex, s, 4))
31 
32 // Similar to packLanguageOrRegion() in ResourceTypes.cpp
encodeLanguageOrRegionLiteral(const char * in,const char base)33 static uint32_t encodeLanguageOrRegionLiteral(const char* in, const char base) {
34   size_t len = strlen(in);
35   if (len <= 1) {
36     return 0;
37   }
38 
39   if (len == 2) {
40       return (((uint8_t) in[0]) << 8) | ((uint8_t) in[1]);
41   }
42   uint8_t first = (in[0] - base) & 0x007f;
43   uint8_t second = (in[1] - base) & 0x007f;
44   uint8_t third = (in[2] - base) & 0x007f;
45 
46   return ((uint8_t) (0x80 | (third << 2) | (second >> 3)) << 8) | ((second << 5) | first);
47 }
48 
encodeLocale(const char * language,const char * region)49 static uint32_t encodeLocale(const char* language, const char* region) {
50     return (encodeLanguageOrRegionLiteral(language, 'a') << 16) |
51             encodeLanguageOrRegionLiteral(region, '0');
52 }
53 
TEST(LocaleDataLookupTest,lookupLikelyScript)54 TEST(LocaleDataLookupTest, lookupLikelyScript) {
55   EXPECT_EQ(nullptr, lookupLikelyScript(encodeLocale("", "")));
56   EXPECT_SCEIPT_EQ("Latn", lookupLikelyScript(encodeLocale("en", "")));
57   EXPECT_EQ(nullptr, lookupLikelyScript(encodeLocale("en", "US")));
58   EXPECT_EQ(nullptr, lookupLikelyScript(encodeLocale("en", "GB")));
59   EXPECT_SCEIPT_EQ("Latn", lookupLikelyScript(encodeLocale("fr", "")));
60   EXPECT_EQ(nullptr, lookupLikelyScript(encodeLocale("fr", "FR")));
61 
62 
63   EXPECT_SCEIPT_EQ("~~~A", lookupLikelyScript(encodeLocale("en", "XA")));
64   EXPECT_SCEIPT_EQ("Latn", lookupLikelyScript(encodeLocale("ha", "")));
65   EXPECT_SCEIPT_EQ("Arab", lookupLikelyScript(encodeLocale("ha", "SD")));
66   EXPECT_EQ(nullptr, lookupLikelyScript(encodeLocale("ha", "Sd"))); // case sensitive
67   EXPECT_SCEIPT_EQ("Hans", lookupLikelyScript(encodeLocale("zh", "")));
68   EXPECT_EQ(nullptr, lookupLikelyScript(encodeLocale("zh", "CN")));
69   EXPECT_SCEIPT_EQ("Hant", lookupLikelyScript(encodeLocale("zh", "HK")));
70 
71   EXPECT_SCEIPT_EQ("Nshu", lookupLikelyScript(encodeLocale("zhx", "")));
72   EXPECT_SCEIPT_EQ("Nshu", lookupLikelyScript(0xDCF90000u)); // encoded "zhx"
73 }
74 
TEST(LocaleDataLookupTest,isLocaleRepresentative)75 TEST(LocaleDataLookupTest, isLocaleRepresentative) {
76   EXPECT_TRUE(isLocaleRepresentative(encodeLocale("en", "US"), "Latn"));
77   EXPECT_TRUE(isLocaleRepresentative(encodeLocale("en", "GB"), "Latn"));
78   EXPECT_FALSE(isLocaleRepresentative(encodeLocale("en", "US"), NULL_SCRIPT));
79   EXPECT_FALSE(isLocaleRepresentative(encodeLocale("en", ""), "Latn"));
80   EXPECT_FALSE(isLocaleRepresentative(encodeLocale("en", ""), NULL_SCRIPT));
81   EXPECT_FALSE(isLocaleRepresentative(encodeLocale("en", "US"), "Arab"));
82 
83   EXPECT_TRUE(isLocaleRepresentative(encodeLocale("fr", "FR"), "Latn"));
84 
85   EXPECT_TRUE(isLocaleRepresentative(encodeLocale("zh", "CN"), "Hans"));
86   EXPECT_FALSE(isLocaleRepresentative(encodeLocale("zh", "TW"), "Hans"));
87   EXPECT_FALSE(isLocaleRepresentative(encodeLocale("zhx", "CN"), "Hans"));
88   EXPECT_FALSE(isLocaleRepresentative(0xDCF9434E, "Hans"));
89   EXPECT_TRUE(isLocaleRepresentative(encodeLocale("zhx", "CN"), "Nshu"));
90   EXPECT_TRUE(isLocaleRepresentative(0xDCF9434E, "Nshu"));
91 }
92 
TEST(LocaleDataLookupTest,findParentLocalePackedKey)93 TEST(LocaleDataLookupTest, findParentLocalePackedKey) {
94   EXPECT_EQ(encodeLocale("en", "001"), findParentLocalePackedKey("Latn", encodeLocale("en", "GB")));
95   EXPECT_EQ(0x656E8400u, findParentLocalePackedKey("Latn", encodeLocale("en", "GB")));
96 
97   EXPECT_EQ(encodeLocale("en", "IN"), findParentLocalePackedKey("Deva", encodeLocale("hi", "")));
98 
99   EXPECT_EQ(encodeLocale("ar", "015"), findParentLocalePackedKey("Arab", encodeLocale("ar", "AE")));
100   EXPECT_EQ(0x61729420u, findParentLocalePackedKey("Arab", encodeLocale("ar", "AE")));
101 
102   EXPECT_EQ(encodeLocale("ar", "015"), findParentLocalePackedKey("~~~B", encodeLocale("ar", "XB")));
103   EXPECT_EQ(0x61729420u, findParentLocalePackedKey("Arab", encodeLocale("ar", "AE")));
104 
105   EXPECT_EQ(encodeLocale("zh", "HK"), findParentLocalePackedKey("Hant", encodeLocale("zh", "MO")));
106 }
107 
108 }  // namespace android
109