blob: f64a8cf209282a90ca81a175491ff96941b010fd [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080018
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080019#include <string>
20
Adam Lesinskid5083f62017-01-16 15:07:21 -080021#include "androidfw/StringPiece.h"
22
Adam Lesinskice5e56e2016-10-21 17:56:45 -070023#include "test/Test.h"
24#include "util/Util.h"
25
Adam Lesinskid5083f62017-01-16 15:07:21 -080026using android::StringPiece;
27using android::StringPiece16;
28
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080029namespace aapt {
30
31TEST(StringPoolTest, InsertOneString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070032 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080033
Adam Lesinskice5e56e2016-10-21 17:56:45 -070034 StringPool::Ref ref = pool.MakeRef("wut");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070035 EXPECT_EQ(*ref, "wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080036}
37
38TEST(StringPoolTest, InsertTwoUniqueStrings) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070039 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080040
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 StringPool::Ref ref = pool.MakeRef("wut");
42 StringPool::Ref ref2 = pool.MakeRef("hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080043
Adam Lesinskicacb28f2016-10-19 12:18:14 -070044 EXPECT_EQ(*ref, "wut");
45 EXPECT_EQ(*ref2, "hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080046}
47
48TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070049 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080050
Adam Lesinskice5e56e2016-10-21 17:56:45 -070051 StringPool::Ref ref = pool.MakeRef("wut");
52 StringPool::Ref ref2 = pool.MakeRef("wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080053
Adam Lesinskicacb28f2016-10-19 12:18:14 -070054 EXPECT_EQ(*ref, "wut");
55 EXPECT_EQ(*ref2, "wut");
56 EXPECT_EQ(1u, pool.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080057}
58
59TEST(StringPoolTest, MaintainInsertionOrderIndex) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080061
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 StringPool::Ref ref = pool.MakeRef("z");
63 StringPool::Ref ref2 = pool.MakeRef("a");
64 StringPool::Ref ref3 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080065
Adam Lesinskice5e56e2016-10-21 17:56:45 -070066 EXPECT_EQ(0u, ref.index());
67 EXPECT_EQ(1u, ref2.index());
68 EXPECT_EQ(2u, ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080069}
70
71TEST(StringPoolTest, PruneStringsWithNoReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080073
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 StringPool::Ref refA = pool.MakeRef("foo");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070076 StringPool::Ref ref = pool.MakeRef("wut");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 EXPECT_EQ(*ref, "wut");
Adam Lesinski1ab598f2015-08-14 14:26:04 -070078 EXPECT_EQ(2u, pool.size());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070079 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070080 StringPool::Ref refB = pool.MakeRef("bar");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070081
82 EXPECT_EQ(3u, pool.size());
Adam Lesinskice5e56e2016-10-21 17:56:45 -070083 pool.Prune();
Adam Lesinskicacb28f2016-10-19 12:18:14 -070084 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);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080091}
92
93TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070094 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080095
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096 StringPool::Ref ref = pool.MakeRef("z");
97 StringPool::StyleRef ref2 = pool.MakeRef(StyleString{{"a"}});
98 StringPool::Ref ref3 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080099
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100 EXPECT_EQ(*ref, "z");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700101 EXPECT_EQ(0u, ref.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800102
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 EXPECT_EQ(*(ref2->str), "a");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104 EXPECT_EQ(1u, ref2.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800105
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700106 EXPECT_EQ(*ref3, "m");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 EXPECT_EQ(2u, ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800108
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 pool.Sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 return a.value < b.value;
111 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800112
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 EXPECT_EQ(*ref, "z");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700114 EXPECT_EQ(2u, ref.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800115
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700116 EXPECT_EQ(*(ref2->str), "a");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 EXPECT_EQ(0u, ref2.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800118
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119 EXPECT_EQ(*ref3, "m");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120 EXPECT_EQ(1u, ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800121}
122
123TEST(StringPoolTest, SortAndStillDedupe) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800125
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700126 StringPool::Ref ref = pool.MakeRef("z");
127 StringPool::Ref ref2 = pool.MakeRef("a");
128 StringPool::Ref ref3 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800129
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 pool.Sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700131 return a.value < b.value;
132 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800133
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700134 StringPool::Ref ref4 = pool.MakeRef("z");
135 StringPool::Ref ref5 = pool.MakeRef("a");
136 StringPool::Ref ref6 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800137
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138 EXPECT_EQ(ref4.index(), ref.index());
139 EXPECT_EQ(ref5.index(), ref2.index());
140 EXPECT_EQ(ref6.index(), ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141}
142
143TEST(StringPoolTest, AddStyles) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800145
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 StyleString str{{"android"}, {Span{{"b"}, 2, 6}}};
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800147
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700148 StringPool::StyleRef ref = pool.MakeRef(str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800149
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700150 EXPECT_EQ(0u, ref.index());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700151 EXPECT_EQ(std::string("android"), *(ref->str));
152 ASSERT_EQ(1u, ref->spans.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800153
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 const StringPool::Span& span = ref->spans.front();
155 EXPECT_EQ(*(span.name), "b");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156 EXPECT_EQ(2u, span.first_char);
157 EXPECT_EQ(6u, span.last_char);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800158}
159
160TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700161 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800162
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 StringPool::Ref ref = pool.MakeRef("android");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800164
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 StyleString str{{"android"}};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 StringPool::StyleRef styleRef = pool.MakeRef(str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800167
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700168 EXPECT_NE(ref.index(), styleRef.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800169}
170
Adam Lesinski769de982015-04-10 19:43:55 -0700171TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700172 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700173
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700174 StringPool pool;
175 BigBuffer buffer(1024);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700176 StringPool::FlattenUtf8(&buffer, pool);
Adam Lesinski769de982015-04-10 19:43:55 -0700177
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700178 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 ResStringPool test;
180 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski769de982015-04-10 19:43:55 -0700181}
182
Adam Lesinski52364f72016-01-11 13:10:24 -0800183TEST(StringPoolTest, FlattenOddCharactersUtf16) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700185
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 StringPool pool;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700187 pool.MakeRef("\u093f");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700188 BigBuffer buffer(1024);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700189 StringPool::FlattenUtf16(&buffer, pool);
Adam Lesinski52364f72016-01-11 13:10:24 -0800190
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700191 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 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]);
Adam Lesinski52364f72016-01-11 13:10:24 -0800199}
200
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201constexpr const char* sLongString =
202 "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑"
203 "え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限"
204 "します。メール、SMSや、同期を使 "
205 "用するその他のアプリは、起動しても更新されないことがあります。バッテリーセ"
206 "ーバーは端末の充電中は自動的にOFFになります。";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800207
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700208TEST(StringPoolTest, Flatten) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700209 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700210
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700211 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800212
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700213 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(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700218 StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800219
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700220 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());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800225
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700226 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 StringPool::FlattenUtf8(&buffers[0], pool);
228 StringPool::FlattenUtf16(&buffers[1], pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800229
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700230 // Test both UTF-8 and UTF-16 buffers.
231 for (const BigBuffer& buffer : buffers) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700233
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700234 ResStringPool test;
235 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800236
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237 EXPECT_EQ(std::string("hello"), util::GetString(test, 0));
238 EXPECT_EQ(StringPiece16(u"hello"), util::GetString16(test, 0));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700239
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 EXPECT_EQ(std::string("goodbye"), util::GetString(test, 1));
241 EXPECT_EQ(StringPiece16(u"goodbye"), util::GetString16(test, 1));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700242
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700243 EXPECT_EQ(StringPiece(sLongString), util::GetString(test, 2));
Adam Lesinskid5083f62017-01-16 15:07:21 -0800244 EXPECT_EQ(util::Utf8ToUtf16(sLongString), util::GetString16(test, 2).to_string());
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700245
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700246 size_t len;
247 EXPECT_TRUE(test.stringAt(3, &len) != nullptr ||
248 test.string8At(3, &len) != nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700249
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 EXPECT_EQ(std::string("style"), util::GetString(test, 4));
251 EXPECT_EQ(StringPiece16(u"style"), util::GetString16(test, 4));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800252
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700253 const ResStringPool_span* span = test.styleAt(4);
254 ASSERT_NE(nullptr, span);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255 EXPECT_EQ(std::string("b"), util::GetString(test, span->name.index));
256 EXPECT_EQ(StringPiece16(u"b"), util::GetString16(test, span->name.index));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 EXPECT_EQ(0u, span->firstChar);
258 EXPECT_EQ(1u, span->lastChar);
259 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800260
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700261 ASSERT_NE(ResStringPool_span::END, span->name.index);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700262 EXPECT_EQ(std::string("i"), util::GetString(test, span->name.index));
263 EXPECT_EQ(StringPiece16(u"i"), util::GetString16(test, span->name.index));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264 EXPECT_EQ(2u, span->firstChar);
265 EXPECT_EQ(3u, span->lastChar);
266 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800267
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 EXPECT_EQ(ResStringPool_span::END, span->name.index);
269 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800270}
271
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700272} // namespace aapt