blob: b1e5ce2e28a8ce1b8560fc9f5c0e6f5924ca0948 [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 Lesinski060b53d2017-07-28 17:10:35 -070026using ::android::StringPiece;
27using ::android::StringPiece16;
28using ::testing::Eq;
29using ::testing::Ne;
30using ::testing::NotNull;
31using ::testing::Pointee;
Adam Lesinskid5083f62017-01-16 15:07:21 -080032
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080033namespace aapt {
34
35TEST(StringPoolTest, InsertOneString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070036 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080037
Adam Lesinskice5e56e2016-10-21 17:56:45 -070038 StringPool::Ref ref = pool.MakeRef("wut");
Adam Lesinski060b53d2017-07-28 17:10:35 -070039 EXPECT_THAT(*ref, Eq("wut"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080040}
41
42TEST(StringPoolTest, InsertTwoUniqueStrings) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070043 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080044
Adam Lesinski060b53d2017-07-28 17:10:35 -070045 StringPool::Ref ref_a = pool.MakeRef("wut");
46 StringPool::Ref ref_b = pool.MakeRef("hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080047
Adam Lesinski060b53d2017-07-28 17:10:35 -070048 EXPECT_THAT(*ref_a, Eq("wut"));
49 EXPECT_THAT(*ref_b, Eq("hey"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080050}
51
52TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070053 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080054
Adam Lesinski060b53d2017-07-28 17:10:35 -070055 StringPool::Ref ref_a = pool.MakeRef("wut");
56 StringPool::Ref ref_b = pool.MakeRef("wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080057
Adam Lesinski060b53d2017-07-28 17:10:35 -070058 EXPECT_THAT(*ref_a, Eq("wut"));
59 EXPECT_THAT(*ref_b, Eq("wut"));
60 EXPECT_THAT(pool.size(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080061}
62
63TEST(StringPoolTest, MaintainInsertionOrderIndex) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070064 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080065
Adam Lesinski060b53d2017-07-28 17:10:35 -070066 StringPool::Ref ref_a = pool.MakeRef("z");
67 StringPool::Ref ref_b = pool.MakeRef("a");
68 StringPool::Ref ref_c = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080069
Adam Lesinski060b53d2017-07-28 17:10:35 -070070 EXPECT_THAT(ref_a.index(), Eq(0u));
71 EXPECT_THAT(ref_b.index(), Eq(1u));
72 EXPECT_THAT(ref_c.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080073}
74
75TEST(StringPoolTest, PruneStringsWithNoReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080077
Adam Lesinski060b53d2017-07-28 17:10:35 -070078 StringPool::Ref ref_a = pool.MakeRef("foo");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070079
Adam Lesinski060b53d2017-07-28 17:10:35 -070080 {
81 StringPool::Ref ref_b = pool.MakeRef("wut");
82 EXPECT_THAT(*ref_b, Eq("wut"));
83 EXPECT_THAT(pool.size(), Eq(2u));
84 pool.Prune();
85 EXPECT_THAT(pool.size(), Eq(2u));
86 }
87 EXPECT_THAT(pool.size(), Eq(2u));
88
89 {
90 StringPool::Ref ref_c = pool.MakeRef("bar");
91 EXPECT_THAT(pool.size(), Eq(3u));
92
93 pool.Prune();
94 EXPECT_THAT(pool.size(), Eq(2u));
95 }
96 EXPECT_THAT(pool.size(), Eq(2u));
97
Adam Lesinskice5e56e2016-10-21 17:56:45 -070098 pool.Prune();
Adam Lesinski060b53d2017-07-28 17:10:35 -070099 EXPECT_THAT(pool.size(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800100}
101
Adam Lesinski060b53d2017-07-28 17:10:35 -0700102TEST(StringPoolTest, SortAndMaintainIndexesInStringReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800104
Adam Lesinski060b53d2017-07-28 17:10:35 -0700105 StringPool::Ref ref_a = pool.MakeRef("z");
106 StringPool::Ref ref_b = pool.MakeRef("a");
107 StringPool::Ref ref_c = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800108
Adam Lesinski060b53d2017-07-28 17:10:35 -0700109 EXPECT_THAT(*ref_a, Eq("z"));
110 EXPECT_THAT(ref_a.index(), Eq(0u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800111
Adam Lesinski060b53d2017-07-28 17:10:35 -0700112 EXPECT_THAT(*ref_b, Eq("a"));
113 EXPECT_THAT(ref_b.index(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800114
Adam Lesinski060b53d2017-07-28 17:10:35 -0700115 EXPECT_THAT(*ref_c, Eq("m"));
116 EXPECT_THAT(ref_c.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800117
Adam Lesinski060b53d2017-07-28 17:10:35 -0700118 pool.Sort();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800119
Adam Lesinski060b53d2017-07-28 17:10:35 -0700120 EXPECT_THAT(*ref_a, Eq("z"));
121 EXPECT_THAT(ref_a.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800122
Adam Lesinski060b53d2017-07-28 17:10:35 -0700123 EXPECT_THAT(*ref_b, Eq("a"));
124 EXPECT_THAT(ref_b.index(), Eq(0u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800125
Adam Lesinski060b53d2017-07-28 17:10:35 -0700126 EXPECT_THAT(*ref_c, Eq("m"));
127 EXPECT_THAT(ref_c.index(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800128}
129
130TEST(StringPoolTest, SortAndStillDedupe) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700131 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800132
Adam Lesinski060b53d2017-07-28 17:10:35 -0700133 StringPool::Ref ref_a = pool.MakeRef("z");
134 StringPool::Ref ref_b = pool.MakeRef("a");
135 StringPool::Ref ref_c = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800136
Adam Lesinski060b53d2017-07-28 17:10:35 -0700137 pool.Sort();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800138
Adam Lesinski060b53d2017-07-28 17:10:35 -0700139 StringPool::Ref ref_d = pool.MakeRef("z");
140 StringPool::Ref ref_e = pool.MakeRef("a");
141 StringPool::Ref ref_f = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800142
Adam Lesinski060b53d2017-07-28 17:10:35 -0700143 EXPECT_THAT(ref_d.index(), Eq(ref_a.index()));
144 EXPECT_THAT(ref_e.index(), Eq(ref_b.index()));
145 EXPECT_THAT(ref_f.index(), Eq(ref_c.index()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800146}
147
148TEST(StringPoolTest, AddStyles) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800150
Adam Lesinski060b53d2017-07-28 17:10:35 -0700151 StringPool::StyleRef ref = pool.MakeRef(StyleString{{"android"}, {Span{{"b"}, 2, 6}}});
152 EXPECT_THAT(ref.index(), Eq(0u));
153 EXPECT_THAT(ref->value, Eq("android"));
154 ASSERT_THAT(ref->spans.size(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800155
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700156 const StringPool::Span& span = ref->spans.front();
Adam Lesinski060b53d2017-07-28 17:10:35 -0700157 EXPECT_THAT(*span.name, Eq("b"));
158 EXPECT_THAT(span.first_char, Eq(2u));
159 EXPECT_THAT(span.last_char, Eq(6u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800160}
161
162TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700163 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800164
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 StringPool::Ref ref = pool.MakeRef("android");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800166
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 StyleString str{{"android"}};
Adam Lesinski060b53d2017-07-28 17:10:35 -0700168 StringPool::StyleRef style_ref = pool.MakeRef(StyleString{{"android"}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800169
Adam Lesinski060b53d2017-07-28 17:10:35 -0700170 EXPECT_THAT(ref.index(), Ne(style_ref.index()));
171}
172
173TEST(StringPoolTest, StylesAndStringsAreSeparateAfterSorting) {
174 StringPool pool;
175
176 StringPool::StyleRef ref_a = pool.MakeRef(StyleString{{"beta"}});
177 StringPool::Ref ref_b = pool.MakeRef("alpha");
178 StringPool::StyleRef ref_c = pool.MakeRef(StyleString{{"alpha"}});
179
180 EXPECT_THAT(ref_b.index(), Ne(ref_c.index()));
181
182 pool.Sort();
183
184 EXPECT_THAT(ref_c.index(), Eq(0u));
185 EXPECT_THAT(ref_a.index(), Eq(1u));
186 EXPECT_THAT(ref_b.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800187}
188
Adam Lesinski769de982015-04-10 19:43:55 -0700189TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700190 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700191
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 StringPool pool;
193 BigBuffer buffer(1024);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700194 StringPool::FlattenUtf8(&buffer, pool);
Adam Lesinski769de982015-04-10 19:43:55 -0700195
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700196 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700197 ResStringPool test;
Adam Lesinski060b53d2017-07-28 17:10:35 -0700198 ASSERT_THAT(test.setTo(data.get(), buffer.size()), Eq(NO_ERROR));
Adam Lesinski769de982015-04-10 19:43:55 -0700199}
200
Adam Lesinski52364f72016-01-11 13:10:24 -0800201TEST(StringPoolTest, FlattenOddCharactersUtf16) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700202 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700203
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 StringPool pool;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700205 pool.MakeRef("\u093f");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700206 BigBuffer buffer(1024);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700207 StringPool::FlattenUtf16(&buffer, pool);
Adam Lesinski52364f72016-01-11 13:10:24 -0800208
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700209 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700210 ResStringPool test;
211 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
212 size_t len = 0;
213 const char16_t* str = test.stringAt(0, &len);
Adam Lesinski060b53d2017-07-28 17:10:35 -0700214 EXPECT_THAT(len, Eq(1u));
215 EXPECT_THAT(str, Pointee(Eq(u'\u093f')));
216 EXPECT_THAT(str[1], Eq(0u));
Adam Lesinski52364f72016-01-11 13:10:24 -0800217}
218
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700219constexpr const char* sLongString =
220 "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑"
221 "え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限"
222 "します。メール、SMSや、同期を使 "
223 "用するその他のアプリは、起動しても更新されないことがあります。バッテリーセ"
224 "ーバーは端末の充電中は自動的にOFFになります。";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800225
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700226TEST(StringPoolTest, Flatten) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700227 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700228
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800230
Adam Lesinski060b53d2017-07-28 17:10:35 -0700231 StringPool::Ref ref_a = pool.MakeRef("hello");
232 StringPool::Ref ref_b = pool.MakeRef("goodbye");
233 StringPool::Ref ref_c = pool.MakeRef(sLongString);
234 StringPool::Ref ref_d = pool.MakeRef("");
235 StringPool::StyleRef ref_e =
236 pool.MakeRef(StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800237
Adam Lesinski060b53d2017-07-28 17:10:35 -0700238 // Styles are always first.
239 EXPECT_THAT(ref_e.index(), Eq(0u));
240
241 EXPECT_THAT(ref_a.index(), Eq(1u));
242 EXPECT_THAT(ref_b.index(), Eq(2u));
243 EXPECT_THAT(ref_c.index(), Eq(3u));
244 EXPECT_THAT(ref_d.index(), Eq(4u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800245
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700246 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700247 StringPool::FlattenUtf8(&buffers[0], pool);
248 StringPool::FlattenUtf16(&buffers[1], pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800249
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700250 // Test both UTF-8 and UTF-16 buffers.
251 for (const BigBuffer& buffer : buffers) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700253
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700254 ResStringPool test;
255 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800256
Adam Lesinski060b53d2017-07-28 17:10:35 -0700257 EXPECT_THAT(util::GetString(test, 1), Eq("hello"));
258 EXPECT_THAT(util::GetString16(test, 1), Eq(u"hello"));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700259
Adam Lesinski060b53d2017-07-28 17:10:35 -0700260 EXPECT_THAT(util::GetString(test, 2), Eq("goodbye"));
261 EXPECT_THAT(util::GetString16(test, 2), Eq(u"goodbye"));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700262
Adam Lesinski060b53d2017-07-28 17:10:35 -0700263 EXPECT_THAT(util::GetString(test, 3), Eq(sLongString));
264 EXPECT_THAT(util::GetString16(test, 3), Eq(util::Utf8ToUtf16(sLongString)));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700265
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700266 size_t len;
Adam Lesinski060b53d2017-07-28 17:10:35 -0700267 EXPECT_TRUE(test.stringAt(4, &len) != nullptr || test.string8At(4, &len) != nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700268
Adam Lesinski060b53d2017-07-28 17:10:35 -0700269 EXPECT_THAT(util::GetString(test, 0), Eq("style"));
270 EXPECT_THAT(util::GetString16(test, 0), Eq(u"style"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800271
Adam Lesinski060b53d2017-07-28 17:10:35 -0700272 const ResStringPool_span* span = test.styleAt(0);
273 ASSERT_THAT(span, NotNull());
274 EXPECT_THAT(util::GetString(test, span->name.index), Eq("b"));
275 EXPECT_THAT(util::GetString16(test, span->name.index), Eq(u"b"));
276 EXPECT_THAT(span->firstChar, Eq(0u));
277 EXPECT_THAT(span->lastChar, Eq(1u));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800279
Adam Lesinski060b53d2017-07-28 17:10:35 -0700280 ASSERT_THAT(span->name.index, Ne(ResStringPool_span::END));
281 EXPECT_THAT(util::GetString(test, span->name.index), Eq("i"));
282 EXPECT_THAT(util::GetString16(test, span->name.index), Eq(u"i"));
283 EXPECT_THAT(span->firstChar, Eq(2u));
284 EXPECT_THAT(span->lastChar, Eq(3u));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700285 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800286
Adam Lesinski060b53d2017-07-28 17:10:35 -0700287 EXPECT_THAT(span->name.index, Eq(ResStringPool_span::END));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700288 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800289}
290
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700291} // namespace aapt