• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "StringPool.h"
18 
19 #include <string>
20 
21 #include "androidfw/StringPiece.h"
22 
23 #include "test/Test.h"
24 #include "util/Util.h"
25 
26 using android::StringPiece;
27 using android::StringPiece16;
28 
29 namespace aapt {
30 
TEST(StringPoolTest,InsertOneString)31 TEST(StringPoolTest, InsertOneString) {
32   StringPool pool;
33 
34   StringPool::Ref ref = pool.MakeRef("wut");
35   EXPECT_EQ(*ref, "wut");
36 }
37 
TEST(StringPoolTest,InsertTwoUniqueStrings)38 TEST(StringPoolTest, InsertTwoUniqueStrings) {
39   StringPool pool;
40 
41   StringPool::Ref ref = pool.MakeRef("wut");
42   StringPool::Ref ref2 = pool.MakeRef("hey");
43 
44   EXPECT_EQ(*ref, "wut");
45   EXPECT_EQ(*ref2, "hey");
46 }
47 
TEST(StringPoolTest,DoNotInsertNewDuplicateString)48 TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
49   StringPool pool;
50 
51   StringPool::Ref ref = pool.MakeRef("wut");
52   StringPool::Ref ref2 = pool.MakeRef("wut");
53 
54   EXPECT_EQ(*ref, "wut");
55   EXPECT_EQ(*ref2, "wut");
56   EXPECT_EQ(1u, pool.size());
57 }
58 
TEST(StringPoolTest,MaintainInsertionOrderIndex)59 TEST(StringPoolTest, MaintainInsertionOrderIndex) {
60   StringPool pool;
61 
62   StringPool::Ref ref = pool.MakeRef("z");
63   StringPool::Ref ref2 = pool.MakeRef("a");
64   StringPool::Ref ref3 = pool.MakeRef("m");
65 
66   EXPECT_EQ(0u, ref.index());
67   EXPECT_EQ(1u, ref2.index());
68   EXPECT_EQ(2u, ref3.index());
69 }
70 
TEST(StringPoolTest,PruneStringsWithNoReferences)71 TEST(StringPoolTest, PruneStringsWithNoReferences) {
72   StringPool pool;
73 
74   StringPool::Ref refA = pool.MakeRef("foo");
75   {
76     StringPool::Ref ref = pool.MakeRef("wut");
77     EXPECT_EQ(*ref, "wut");
78     EXPECT_EQ(2u, pool.size());
79   }
80   StringPool::Ref refB = pool.MakeRef("bar");
81 
82   EXPECT_EQ(3u, pool.size());
83   pool.Prune();
84   EXPECT_EQ(2u, pool.size());
85   StringPool::const_iterator iter = begin(pool);
86   EXPECT_EQ((*iter)->value, "foo");
87   EXPECT_LT((*iter)->index, 2u);
88   ++iter;
89   EXPECT_EQ((*iter)->value, "bar");
90   EXPECT_LT((*iter)->index, 2u);
91 }
92 
TEST(StringPoolTest,SortAndMaintainIndexesInReferences)93 TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
94   StringPool pool;
95 
96   StringPool::Ref ref = pool.MakeRef("z");
97   StringPool::StyleRef ref2 = pool.MakeRef(StyleString{{"a"}});
98   StringPool::Ref ref3 = pool.MakeRef("m");
99 
100   EXPECT_EQ(*ref, "z");
101   EXPECT_EQ(0u, ref.index());
102 
103   EXPECT_EQ(*(ref2->str), "a");
104   EXPECT_EQ(1u, ref2.index());
105 
106   EXPECT_EQ(*ref3, "m");
107   EXPECT_EQ(2u, ref3.index());
108 
109   pool.Sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
110     return a.value < b.value;
111   });
112 
113   EXPECT_EQ(*ref, "z");
114   EXPECT_EQ(2u, ref.index());
115 
116   EXPECT_EQ(*(ref2->str), "a");
117   EXPECT_EQ(0u, ref2.index());
118 
119   EXPECT_EQ(*ref3, "m");
120   EXPECT_EQ(1u, ref3.index());
121 }
122 
TEST(StringPoolTest,SortAndStillDedupe)123 TEST(StringPoolTest, SortAndStillDedupe) {
124   StringPool pool;
125 
126   StringPool::Ref ref = pool.MakeRef("z");
127   StringPool::Ref ref2 = pool.MakeRef("a");
128   StringPool::Ref ref3 = pool.MakeRef("m");
129 
130   pool.Sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
131     return a.value < b.value;
132   });
133 
134   StringPool::Ref ref4 = pool.MakeRef("z");
135   StringPool::Ref ref5 = pool.MakeRef("a");
136   StringPool::Ref ref6 = pool.MakeRef("m");
137 
138   EXPECT_EQ(ref4.index(), ref.index());
139   EXPECT_EQ(ref5.index(), ref2.index());
140   EXPECT_EQ(ref6.index(), ref3.index());
141 }
142 
TEST(StringPoolTest,AddStyles)143 TEST(StringPoolTest, AddStyles) {
144   StringPool pool;
145 
146   StyleString str{{"android"}, {Span{{"b"}, 2, 6}}};
147 
148   StringPool::StyleRef ref = pool.MakeRef(str);
149 
150   EXPECT_EQ(0u, ref.index());
151   EXPECT_EQ(std::string("android"), *(ref->str));
152   ASSERT_EQ(1u, ref->spans.size());
153 
154   const StringPool::Span& span = ref->spans.front();
155   EXPECT_EQ(*(span.name), "b");
156   EXPECT_EQ(2u, span.first_char);
157   EXPECT_EQ(6u, span.last_char);
158 }
159 
TEST(StringPoolTest,DoNotDedupeStyleWithSameStringAsNonStyle)160 TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
161   StringPool pool;
162 
163   StringPool::Ref ref = pool.MakeRef("android");
164 
165   StyleString str{{"android"}};
166   StringPool::StyleRef styleRef = pool.MakeRef(str);
167 
168   EXPECT_NE(ref.index(), styleRef.index());
169 }
170 
TEST(StringPoolTest,FlattenEmptyStringPoolUtf8)171 TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
172   using namespace android;  // For NO_ERROR on Windows.
173 
174   StringPool pool;
175   BigBuffer buffer(1024);
176   StringPool::FlattenUtf8(&buffer, pool);
177 
178   std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
179   ResStringPool test;
180   ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
181 }
182 
TEST(StringPoolTest,FlattenOddCharactersUtf16)183 TEST(StringPoolTest, FlattenOddCharactersUtf16) {
184   using namespace android;  // For NO_ERROR on Windows.
185 
186   StringPool pool;
187   pool.MakeRef("\u093f");
188   BigBuffer buffer(1024);
189   StringPool::FlattenUtf16(&buffer, pool);
190 
191   std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
192   ResStringPool test;
193   ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
194   size_t len = 0;
195   const char16_t* str = test.stringAt(0, &len);
196   EXPECT_EQ(1u, len);
197   EXPECT_EQ(u'\u093f', *str);
198   EXPECT_EQ(0u, str[1]);
199 }
200 
201 constexpr const char* sLongString =
202     "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑"
203     "え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限"
204     "します。メール、SMSや、同期を使 "
205     "用するその他のアプリは、起動しても更新されないことがあります。バッテリーセ"
206     "ーバーは端末の充電中は自動的にOFFになります。";
207 
TEST(StringPoolTest,Flatten)208 TEST(StringPoolTest, Flatten) {
209   using namespace android;  // For NO_ERROR on Windows.
210 
211   StringPool pool;
212 
213   StringPool::Ref ref1 = pool.MakeRef("hello");
214   StringPool::Ref ref2 = pool.MakeRef("goodbye");
215   StringPool::Ref ref3 = pool.MakeRef(sLongString);
216   StringPool::Ref ref4 = pool.MakeRef("");
217   StringPool::StyleRef ref5 = pool.MakeRef(
218       StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}});
219 
220   EXPECT_EQ(0u, ref1.index());
221   EXPECT_EQ(1u, ref2.index());
222   EXPECT_EQ(2u, ref3.index());
223   EXPECT_EQ(3u, ref4.index());
224   EXPECT_EQ(4u, ref5.index());
225 
226   BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
227   StringPool::FlattenUtf8(&buffers[0], pool);
228   StringPool::FlattenUtf16(&buffers[1], pool);
229 
230   // Test both UTF-8 and UTF-16 buffers.
231   for (const BigBuffer& buffer : buffers) {
232     std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
233 
234     ResStringPool test;
235     ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
236 
237     EXPECT_EQ(std::string("hello"), util::GetString(test, 0));
238     EXPECT_EQ(StringPiece16(u"hello"), util::GetString16(test, 0));
239 
240     EXPECT_EQ(std::string("goodbye"), util::GetString(test, 1));
241     EXPECT_EQ(StringPiece16(u"goodbye"), util::GetString16(test, 1));
242 
243     EXPECT_EQ(StringPiece(sLongString), util::GetString(test, 2));
244     EXPECT_EQ(util::Utf8ToUtf16(sLongString), util::GetString16(test, 2).to_string());
245 
246     size_t len;
247     EXPECT_TRUE(test.stringAt(3, &len) != nullptr ||
248                 test.string8At(3, &len) != nullptr);
249 
250     EXPECT_EQ(std::string("style"), util::GetString(test, 4));
251     EXPECT_EQ(StringPiece16(u"style"), util::GetString16(test, 4));
252 
253     const ResStringPool_span* span = test.styleAt(4);
254     ASSERT_NE(nullptr, span);
255     EXPECT_EQ(std::string("b"), util::GetString(test, span->name.index));
256     EXPECT_EQ(StringPiece16(u"b"), util::GetString16(test, span->name.index));
257     EXPECT_EQ(0u, span->firstChar);
258     EXPECT_EQ(1u, span->lastChar);
259     span++;
260 
261     ASSERT_NE(ResStringPool_span::END, span->name.index);
262     EXPECT_EQ(std::string("i"), util::GetString(test, span->name.index));
263     EXPECT_EQ(StringPiece16(u"i"), util::GetString16(test, span->name.index));
264     EXPECT_EQ(2u, span->firstChar);
265     EXPECT_EQ(3u, span->lastChar);
266     span++;
267 
268     EXPECT_EQ(ResStringPool_span::END, span->name.index);
269   }
270 }
271 
272 }  // namespace aapt
273