1 /* 2 * Copyright (C) 2015 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/Pseudolocalizer.h" 18 #include "util/Util.h" 19 20 #include <androidfw/ResourceTypes.h> 21 #include <gtest/gtest.h> 22 23 namespace aapt { 24 25 // In this context, 'Axis' represents a particular field in the configuration, 26 // such as language or density. 27 28 static ::testing::AssertionResult simpleHelper(const char* input, const char* expected, 29 Pseudolocalizer::Method method) { 30 Pseudolocalizer pseudo(method); 31 std::string result = util::utf16ToUtf8( 32 pseudo.start() + pseudo.text(util::utf8ToUtf16(input)) + pseudo.end()); 33 if (StringPiece(expected) != result) { 34 return ::testing::AssertionFailure() << expected << " != " << result; 35 } 36 return ::testing::AssertionSuccess(); 37 } 38 39 static ::testing::AssertionResult compoundHelper(const char* in1, const char* in2, const char *in3, 40 const char* expected, 41 Pseudolocalizer::Method method) { 42 Pseudolocalizer pseudo(method); 43 std::string result = util::utf16ToUtf8(pseudo.start() + 44 pseudo.text(util::utf8ToUtf16(in1)) + 45 pseudo.text(util::utf8ToUtf16(in2)) + 46 pseudo.text(util::utf8ToUtf16(in3)) + 47 pseudo.end()); 48 if (StringPiece(expected) != result) { 49 return ::testing::AssertionFailure() << expected << " != " << result; 50 } 51 return ::testing::AssertionSuccess(); 52 } 53 54 TEST(PseudolocalizerTest, NoPseudolocalization) { 55 EXPECT_TRUE(simpleHelper("", "", Pseudolocalizer::Method::kNone)); 56 EXPECT_TRUE(simpleHelper("Hello, world", "Hello, world", Pseudolocalizer::Method::kNone)); 57 58 EXPECT_TRUE(compoundHelper("Hello,", " world", "", 59 "Hello, world", Pseudolocalizer::Method::kNone)); 60 } 61 62 TEST(PseudolocalizerTest, PlaintextAccent) { 63 EXPECT_TRUE(simpleHelper("", "[]", Pseudolocalizer::Method::kAccent)); 64 EXPECT_TRUE(simpleHelper("Hello, world", 65 "[, one two]", Pseudolocalizer::Method::kAccent)); 66 67 EXPECT_TRUE(simpleHelper("Hello, %1d", 68 "[, %1d one two]", Pseudolocalizer::Method::kAccent)); 69 70 EXPECT_TRUE(simpleHelper("Battery %1d%%", 71 "[ %1d%% one two]", Pseudolocalizer::Method::kAccent)); 72 73 EXPECT_TRUE(compoundHelper("", "", "", "[]", Pseudolocalizer::Method::kAccent)); 74 EXPECT_TRUE(compoundHelper("Hello,", " world", "", 75 "[, one two]", Pseudolocalizer::Method::kAccent)); 76 } 77 78 TEST(PseudolocalizerTest, PlaintextBidi) { 79 EXPECT_TRUE(simpleHelper("", "", Pseudolocalizer::Method::kBidi)); 80 EXPECT_TRUE(simpleHelper("word", 81 "\xe2\x80\x8f\xE2\x80\xaeword\xE2\x80\xac\xe2\x80\x8f", 82 Pseudolocalizer::Method::kBidi)); 83 EXPECT_TRUE(simpleHelper(" word ", 84 " \xe2\x80\x8f\xE2\x80\xaeword\xE2\x80\xac\xe2\x80\x8f ", 85 Pseudolocalizer::Method::kBidi)); 86 EXPECT_TRUE(simpleHelper(" word ", 87 " \xe2\x80\x8f\xE2\x80\xaeword\xE2\x80\xac\xe2\x80\x8f ", 88 Pseudolocalizer::Method::kBidi)); 89 EXPECT_TRUE(simpleHelper("hello\n world\n", 90 "\xe2\x80\x8f\xE2\x80\xaehello\xE2\x80\xac\xe2\x80\x8f\n" \ 91 " \xe2\x80\x8f\xE2\x80\xaeworld\xE2\x80\xac\xe2\x80\x8f\n", 92 Pseudolocalizer::Method::kBidi)); 93 EXPECT_TRUE(compoundHelper("hello", "\n ", " world\n", 94 "\xe2\x80\x8f\xE2\x80\xaehello\xE2\x80\xac\xe2\x80\x8f\n" \ 95 " \xe2\x80\x8f\xE2\x80\xaeworld\xE2\x80\xac\xe2\x80\x8f\n", 96 Pseudolocalizer::Method::kBidi)); 97 } 98 99 TEST(PseudolocalizerTest, SimpleICU) { 100 // Single-fragment messages 101 EXPECT_TRUE(simpleHelper("{placeholder}", "[{placeholder}]", 102 Pseudolocalizer::Method::kAccent)); 103 EXPECT_TRUE(simpleHelper("{USER} is offline", 104 "[{USER} one two]", Pseudolocalizer::Method::kAccent)); 105 EXPECT_TRUE(simpleHelper("Copy from {path1} to {path2}", 106 "[ {path1} {path2} one two three]", 107 Pseudolocalizer::Method::kAccent)); 108 EXPECT_TRUE(simpleHelper("Today is {1,date} {1,time}", 109 "[ {1,date} {1,time} one two]", 110 Pseudolocalizer::Method::kAccent)); 111 112 // Multi-fragment messages 113 EXPECT_TRUE(compoundHelper("{USER}", " ", "is offline", 114 "[{USER} one two]", 115 Pseudolocalizer::Method::kAccent)); 116 EXPECT_TRUE(compoundHelper("Copy from ", "{path1}", " to {path2}", 117 "[ {path1} {path2} one two three]", 118 Pseudolocalizer::Method::kAccent)); 119 } 120 121 TEST(PseudolocalizerTest, ICUBidi) { 122 // Single-fragment messages 123 EXPECT_TRUE(simpleHelper("{placeholder}", 124 "\xe2\x80\x8f\xE2\x80\xae{placeholder}\xE2\x80\xac\xe2\x80\x8f", 125 Pseudolocalizer::Method::kBidi)); 126 EXPECT_TRUE(simpleHelper( 127 "{COUNT, plural, one {one} other {other}}", 128 "{COUNT, plural, " \ 129 "one {\xe2\x80\x8f\xE2\x80\xaeone\xE2\x80\xac\xe2\x80\x8f} " \ 130 "other {\xe2\x80\x8f\xE2\x80\xaeother\xE2\x80\xac\xe2\x80\x8f}}", 131 Pseudolocalizer::Method::kBidi)); 132 } 133 134 TEST(PseudolocalizerTest, Escaping) { 135 // Single-fragment messages 136 EXPECT_TRUE(simpleHelper("'{USER'} is offline", 137 "['{'} one two three]", 138 Pseudolocalizer::Method::kAccent)); 139 140 // Multi-fragment messages 141 EXPECT_TRUE(compoundHelper("'{USER}", " ", "''is offline", 142 "['{} '' one two three]", 143 Pseudolocalizer::Method::kAccent)); 144 } 145 146 TEST(PseudolocalizerTest, PluralsAndSelects) { 147 EXPECT_TRUE(simpleHelper( 148 "{COUNT, plural, one {Delete a file} other {Delete {COUNT} files}}", 149 "[{COUNT, plural, one { one two} " \ 150 "other { {COUNT} one two}}]", 151 Pseudolocalizer::Method::kAccent)); 152 153 EXPECT_TRUE(simpleHelper( 154 "Distance is {COUNT, plural, one {# mile} other {# miles}}", 155 "[ {COUNT, plural, one {# one two} " \ 156 "other {# one two}}]", 157 Pseudolocalizer::Method::kAccent)); 158 159 EXPECT_TRUE(simpleHelper( 160 "{1, select, female {{1} added you} " \ 161 "male {{1} added you} other {{1} added you}}", 162 "[{1, select, female {{1} one two} " \ 163 "male {{1} one two} other {{1} one two}}]", 164 Pseudolocalizer::Method::kAccent)); 165 166 EXPECT_TRUE(compoundHelper( 167 "{COUNT, plural, one {Delete a file} " \ 168 "other {Delete ", "{COUNT}", " files}}", 169 "[{COUNT, plural, one { one two} " \ 170 "other { {COUNT} one two}}]", 171 Pseudolocalizer::Method::kAccent)); 172 } 173 174 TEST(PseudolocalizerTest, NestedICU) { 175 EXPECT_TRUE(simpleHelper( 176 "{person, select, " \ 177 "female {" \ 178 "{num_circles, plural," \ 179 "=0{{person} didn't add you to any of her circles.}" \ 180 "=1{{person} added you to one of her circles.}" \ 181 "other{{person} added you to her # circles.}}}" \ 182 "male {" \ 183 "{num_circles, plural," \ 184 "=0{{person} didn't add you to any of his circles.}" \ 185 "=1{{person} added you to one of his circles.}" \ 186 "other{{person} added you to his # circles.}}}" \ 187 "other {" \ 188 "{num_circles, plural," \ 189 "=0{{person} didn't add you to any of their circles.}" \ 190 "=1{{person} added you to one of their circles.}" \ 191 "other{{person} added you to their # circles.}}}}", 192 "[{person, select, " \ 193 "female {" \ 194 "{num_circles, plural," \ 195 "=0{{person} ' ." \ 196 " one two three four five}" \ 197 "=1{{person} ." \ 198 " one two three four}" \ 199 "other{{person} # ." \ 200 " one two three four}}}" \ 201 "male {" \ 202 "{num_circles, plural," \ 203 "=0{{person} ' ." \ 204 " one two three four five}" \ 205 "=1{{person} ." \ 206 " one two three four}" \ 207 "other{{person} # ." \ 208 " one two three four}}}" \ 209 "other {{num_circles, plural," \ 210 "=0{{person} ' ." \ 211 " one two three four five}" \ 212 "=1{{person} ." \ 213 " one two three four}" \ 214 "other{{person} # ." \ 215 " one two three four}}}}]", 216 Pseudolocalizer::Method::kAccent)); 217 } 218 219 TEST(PseudolocalizerTest, RedefineMethod) { 220 Pseudolocalizer pseudo(Pseudolocalizer::Method::kAccent); 221 std::u16string result = pseudo.text(u"Hello, "); 222 pseudo.setMethod(Pseudolocalizer::Method::kNone); 223 result += pseudo.text(u"world!"); 224 ASSERT_EQ(StringPiece(", world!"), util::utf16ToUtf8(result)); 225 } 226 227 } // namespace aapt 228