• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 "compile/PseudolocaleGenerator.h"
18 
19 #include "test/Test.h"
20 #include "util/Util.h"
21 
22 namespace aapt {
23 
TEST(PseudolocaleGeneratorTest,PseudolocalizeStyledString)24 TEST(PseudolocaleGeneratorTest, PseudolocalizeStyledString) {
25   StringPool pool;
26   StyleString original_style;
27   original_style.str = "Hello world!";
28   original_style.spans = {Span{"i", 1, 10}, Span{"b", 2, 3}, Span{"b", 6, 7}};
29 
30   std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
31       util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
32       Pseudolocalizer::Method::kNone, &pool);
33 
34   EXPECT_EQ(original_style.str, new_string->value->value);
35   ASSERT_EQ(original_style.spans.size(), new_string->value->spans.size());
36 
37   EXPECT_EQ(std::string("i"), *new_string->value->spans[0].name);
38   EXPECT_EQ(std::u16string(u"H").size(), new_string->value->spans[0].first_char);
39   EXPECT_EQ(std::u16string(u"Hello worl").size(), new_string->value->spans[0].last_char);
40 
41   EXPECT_EQ(std::string("b"), *new_string->value->spans[1].name);
42   EXPECT_EQ(std::u16string(u"He").size(), new_string->value->spans[1].first_char);
43   EXPECT_EQ(std::u16string(u"Hel").size(), new_string->value->spans[1].last_char);
44 
45   EXPECT_EQ(std::string("b"), *new_string->value->spans[2].name);
46   EXPECT_EQ(std::u16string(u"Hello ").size(), new_string->value->spans[2].first_char);
47   EXPECT_EQ(std::u16string(u"Hello w").size(), new_string->value->spans[2].last_char);
48 
49   original_style.spans.insert(original_style.spans.begin(), Span{"em", 0, 11u});
50 
51   new_string = PseudolocalizeStyledString(
52       util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
53       Pseudolocalizer::Method::kAccent, &pool);
54 
55   EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļð¡ one two]"), new_string->value->value);
56   ASSERT_EQ(original_style.spans.size(), new_string->value->spans.size());
57 
58   EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[0].first_char);
59   EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵöŕļð").size(), new_string->value->spans[0].last_char);
60 
61   EXPECT_EQ(std::u16string(u"[Ĥ").size(), new_string->value->spans[1].first_char);
62   EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵöŕļ").size(), new_string->value->spans[1].last_char);
63 
64   EXPECT_EQ(std::u16string(u"[Ĥé").size(), new_string->value->spans[2].first_char);
65   EXPECT_EQ(std::u16string(u"[Ĥéļ").size(), new_string->value->spans[2].last_char);
66 
67   EXPECT_EQ(std::u16string(u"[Ĥéļļö ").size(), new_string->value->spans[3].first_char);
68   EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵ").size(), new_string->value->spans[3].last_char);
69 }
70 
TEST(PseudolocaleGeneratorTest,PseudolocalizeAdjacentNestedTags)71 TEST(PseudolocaleGeneratorTest, PseudolocalizeAdjacentNestedTags) {
72   StringPool pool;
73   StyleString original_style;
74   original_style.str = "bold";
75   original_style.spans = {Span{"b", 0, 3}, Span{"i", 0, 3}};
76 
77   std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
78       util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
79       Pseudolocalizer::Method::kAccent, &pool);
80   ASSERT_NE(nullptr, new_string);
81   ASSERT_EQ(2u, new_string->value->spans.size());
82   EXPECT_EQ(std::string("[ɓöļð one]"), new_string->value->value);
83 
84   EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
85   EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[0].first_char);
86   EXPECT_EQ(std::u16string(u"[ɓöļ").size(), new_string->value->spans[0].last_char);
87 
88   EXPECT_EQ(std::string("i"), *new_string->value->spans[1].name);
89   EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[1].first_char);
90   EXPECT_EQ(std::u16string(u"[ɓöļ").size(), new_string->value->spans[1].last_char);
91 }
92 
TEST(PseudolocaleGeneratorTest,PseudolocalizeAdjacentTagsUnsorted)93 TEST(PseudolocaleGeneratorTest, PseudolocalizeAdjacentTagsUnsorted) {
94   StringPool pool;
95   StyleString original_style;
96   original_style.str = "bold";
97   original_style.spans = {Span{"i", 2, 3}, Span{"b", 0, 1}};
98 
99   std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
100       util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
101       Pseudolocalizer::Method::kAccent, &pool);
102   ASSERT_NE(nullptr, new_string);
103   ASSERT_EQ(2u, new_string->value->spans.size());
104   EXPECT_EQ(std::string("[ɓöļð one]"), new_string->value->value);
105 
106   EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
107   EXPECT_EQ(std::u16string(u"[").size(), new_string->value->spans[0].first_char);
108   EXPECT_EQ(std::u16string(u"[ɓ").size(), new_string->value->spans[0].last_char);
109 
110   EXPECT_EQ(std::string("i"), *new_string->value->spans[1].name);
111   EXPECT_EQ(std::u16string(u"[ɓö").size(), new_string->value->spans[1].first_char);
112   EXPECT_EQ(std::u16string(u"[ɓöļ").size(), new_string->value->spans[1].last_char);
113 }
114 
TEST(PseudolocaleGeneratorTest,PseudolocalizeNestedAndAdjacentTags)115 TEST(PseudolocaleGeneratorTest, PseudolocalizeNestedAndAdjacentTags) {
116   StringPool pool;
117   StyleString original_style;
118   original_style.str = "This sentence is not what you think it is at all.";
119   original_style.spans = {Span{"b", 16u, 19u}, Span{"em", 29u, 47u}, Span{"i", 38u, 40u},
120                           Span{"b", 44u, 47u}};
121 
122   std::unique_ptr<StyledString> new_string = PseudolocalizeStyledString(
123       util::make_unique<StyledString>(pool.MakeRef(original_style)).get(),
124       Pseudolocalizer::Method::kAccent, &pool);
125   ASSERT_NE(nullptr, new_string);
126   ASSERT_EQ(4u, new_string->value->spans.size());
127   EXPECT_EQ(std::string(
128                 "[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ åļļ. one two three four five six]"),
129             new_string->value->value);
130 
131   EXPECT_EQ(std::string("b"), *new_string->value->spans[0].name);
132   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš").size(), new_string->value->spans[0].first_char);
133   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñö").size(), new_string->value->spans[0].last_char);
134 
135   EXPECT_EQ(std::string("em"), *new_string->value->spans[1].name);
136   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû").size(),
137             new_string->value->spans[1].first_char);
138   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ åļ").size(),
139             new_string->value->spans[1].last_char);
140 
141   EXPECT_EQ(std::string("i"), *new_string->value->spans[2].name);
142   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ").size(),
143             new_string->value->spans[2].first_char);
144   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ î").size(),
145             new_string->value->spans[2].last_char);
146 
147   EXPECT_EQ(std::string("b"), *new_string->value->spans[3].name);
148   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ").size(),
149             new_string->value->spans[3].first_char);
150   EXPECT_EQ(std::u16string(u"[Ţĥîš šéñţéñçé îš ñöţ ŵĥåţ ýöû ţĥîñķ îţ îš åţ åļ").size(),
151             new_string->value->spans[3].last_char);
152 }
153 
TEST(PseudolocaleGeneratorTest,PseudolocalizePartsOfString)154 TEST(PseudolocaleGeneratorTest, PseudolocalizePartsOfString) {
155   StringPool pool;
156   StyleString original_style;
157   original_style.str = "This should NOT be pseudolocalized.";
158   original_style.spans = {Span{"em", 4u, 14u}, Span{"i", 18u, 33u}};
159   std::unique_ptr<StyledString> original_string =
160       util::make_unique<StyledString>(pool.MakeRef(original_style));
161   original_string->untranslatable_sections = {UntranslatableSection{11u, 15u}};
162 
163   std::unique_ptr<StyledString> new_string =
164       PseudolocalizeStyledString(original_string.get(), Pseudolocalizer::Method::kAccent, &pool);
165   ASSERT_NE(nullptr, new_string);
166   ASSERT_EQ(2u, new_string->value->spans.size());
167   EXPECT_EQ(std::string("[Ţĥîš šĥöûļð NOT ɓé þšéûðöļöçåļîžéð. one two three four]"),
168             new_string->value->value);
169 
170   EXPECT_EQ(std::string("em"), *new_string->value->spans[0].name);
171   EXPECT_EQ(std::u16string(u"[Ţĥîš").size(), new_string->value->spans[0].first_char);
172   EXPECT_EQ(std::u16string(u"[Ţĥîš šĥöûļð NO").size(), new_string->value->spans[0].last_char);
173 
174   EXPECT_EQ(std::string("i"), *new_string->value->spans[1].name);
175   EXPECT_EQ(std::u16string(u"[Ţĥîš šĥöûļð NOT ɓé").size(), new_string->value->spans[1].first_char);
176   EXPECT_EQ(std::u16string(u"[Ţĥîš šĥöûļð NOT ɓé þšéûðöļöçåļîžé").size(),
177             new_string->value->spans[1].last_char);
178 }
179 
TEST(PseudolocaleGeneratorTest,PseudolocalizeOnlyDefaultConfigs)180 TEST(PseudolocaleGeneratorTest, PseudolocalizeOnlyDefaultConfigs) {
181   std::unique_ptr<ResourceTable> table =
182       test::ResourceTableBuilder()
183           .AddString("android:string/one", "one")
184           .AddString("android:string/two", ResourceId{},
185                      test::ParseConfigOrDie("en"), "two")
186           .AddString("android:string/three", "three")
187           .AddString("android:string/three", ResourceId{},
188                      test::ParseConfigOrDie("en-rXA"), "three")
189           .AddString("android:string/four", "four")
190           .Build();
191 
192   String* val = test::GetValue<String>(table.get(), "android:string/four");
193   ASSERT_NE(nullptr, val);
194   val->SetTranslatable(false);
195 
196   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
197   PseudolocaleGenerator generator;
198   ASSERT_TRUE(generator.Consume(context.get(), table.get()));
199 
200   // Normal pseudolocalization should take place.
201   ASSERT_NE(nullptr,
202             test::GetValueForConfig<String>(table.get(), "android:string/one",
203                                             test::ParseConfigOrDie("en-rXA")));
204   ASSERT_NE(nullptr,
205             test::GetValueForConfig<String>(table.get(), "android:string/one",
206                                             test::ParseConfigOrDie("ar-rXB")));
207 
208   // No default config for android:string/two, so no pseudlocales should exist.
209   ASSERT_EQ(nullptr,
210             test::GetValueForConfig<String>(table.get(), "android:string/two",
211                                             test::ParseConfigOrDie("en-rXA")));
212   ASSERT_EQ(nullptr,
213             test::GetValueForConfig<String>(table.get(), "android:string/two",
214                                             test::ParseConfigOrDie("ar-rXB")));
215 
216   // Check that we didn't override manual pseudolocalization.
217   val = test::GetValueForConfig<String>(table.get(), "android:string/three",
218                                         test::ParseConfigOrDie("en-rXA"));
219   ASSERT_NE(nullptr, val);
220   EXPECT_EQ(std::string("three"), *val->value);
221 
222   ASSERT_NE(nullptr,
223             test::GetValueForConfig<String>(table.get(), "android:string/three",
224                                             test::ParseConfigOrDie("ar-rXB")));
225 
226   // Check that four's translateable marker was honored.
227   ASSERT_EQ(nullptr,
228             test::GetValueForConfig<String>(table.get(), "android:string/four",
229                                             test::ParseConfigOrDie("en-rXA")));
230   ASSERT_EQ(nullptr,
231             test::GetValueForConfig<String>(table.get(), "android:string/four",
232                                             test::ParseConfigOrDie("ar-rXB")));
233 }
234 
TEST(PseudolocaleGeneratorTest,RespectUntranslateableSections)235 TEST(PseudolocaleGeneratorTest, RespectUntranslateableSections) {
236   std::unique_ptr<IAaptContext> context =
237       test::ContextBuilder().SetCompilationPackage("android").Build();
238   std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
239 
240   {
241     StyleString original_style;
242     original_style.str = "Hello world!";
243     original_style.spans = {Span{"i", 1, 10}, Span{"b", 2, 3}, Span{"b", 6, 7}};
244 
245     auto styled_string =
246         util::make_unique<StyledString>(table->string_pool.MakeRef(original_style));
247     styled_string->untranslatable_sections.push_back(UntranslatableSection{6u, 8u});
248     styled_string->untranslatable_sections.push_back(UntranslatableSection{8u, 11u});
249 
250     auto string = util::make_unique<String>(table->string_pool.MakeRef(original_style.str));
251     string->untranslatable_sections.push_back(UntranslatableSection{6u, 11u});
252 
253     ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("android:string/foo"), ConfigDescription{},
254                                    {} /* product */, std::move(styled_string),
255                                    context->GetDiagnostics()));
256     ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("android:string/bar"), ConfigDescription{},
257                                    {} /* product */, std::move(string), context->GetDiagnostics()));
258   }
259 
260   PseudolocaleGenerator generator;
261   ASSERT_TRUE(generator.Consume(context.get(), table.get()));
262 
263   StyledString* new_styled_string = test::GetValueForConfig<StyledString>(
264       table.get(), "android:string/foo", test::ParseConfigOrDie("en-rXA"));
265   ASSERT_NE(nullptr, new_styled_string);
266 
267   // "world" should be untranslated.
268   EXPECT_NE(std::string::npos, new_styled_string->value->value.find("world"));
269 
270   String* new_string = test::GetValueForConfig<String>(table.get(), "android:string/bar",
271                                                        test::ParseConfigOrDie("en-rXA"));
272   ASSERT_NE(nullptr, new_string);
273 
274   // "world" should be untranslated.
275   EXPECT_NE(std::string::npos, new_string->value->find("world"));
276 }
277 
278 }  // namespace aapt
279