blob: 2a7e1dd6a231f32e1bb802d34138914c07177ad0 [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 Lesinskid0f116b2016-07-08 15:00:32 -070018#include "test/Test.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070019#include "util/Util.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080020
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080021#include <string>
22
23namespace aapt {
24
25TEST(StringPoolTest, InsertOneString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070026 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080027
Adam Lesinskicacb28f2016-10-19 12:18:14 -070028 StringPool::Ref ref = pool.makeRef("wut");
29 EXPECT_EQ(*ref, "wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080030}
31
32TEST(StringPoolTest, InsertTwoUniqueStrings) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070033 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080034
Adam Lesinskicacb28f2016-10-19 12:18:14 -070035 StringPool::Ref ref = pool.makeRef("wut");
36 StringPool::Ref ref2 = pool.makeRef("hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080037
Adam Lesinskicacb28f2016-10-19 12:18:14 -070038 EXPECT_EQ(*ref, "wut");
39 EXPECT_EQ(*ref2, "hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080040}
41
42TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070043 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080044
Adam Lesinskicacb28f2016-10-19 12:18:14 -070045 StringPool::Ref ref = pool.makeRef("wut");
46 StringPool::Ref ref2 = pool.makeRef("wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080047
Adam Lesinskicacb28f2016-10-19 12:18:14 -070048 EXPECT_EQ(*ref, "wut");
49 EXPECT_EQ(*ref2, "wut");
50 EXPECT_EQ(1u, pool.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080051}
52
53TEST(StringPoolTest, MaintainInsertionOrderIndex) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070054 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080055
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 StringPool::Ref ref = pool.makeRef("z");
57 StringPool::Ref ref2 = pool.makeRef("a");
58 StringPool::Ref ref3 = pool.makeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080059
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 EXPECT_EQ(0u, ref.getIndex());
61 EXPECT_EQ(1u, ref2.getIndex());
62 EXPECT_EQ(2u, ref3.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080063}
64
65TEST(StringPoolTest, PruneStringsWithNoReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080067
Adam Lesinskicacb28f2016-10-19 12:18:14 -070068 StringPool::Ref refA = pool.makeRef("foo");
69 {
70 StringPool::Ref ref = pool.makeRef("wut");
71 EXPECT_EQ(*ref, "wut");
Adam Lesinski1ab598f2015-08-14 14:26:04 -070072 EXPECT_EQ(2u, pool.size());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070073 }
74 StringPool::Ref refB = pool.makeRef("bar");
75
76 EXPECT_EQ(3u, pool.size());
77 pool.prune();
78 EXPECT_EQ(2u, pool.size());
79 StringPool::const_iterator iter = begin(pool);
80 EXPECT_EQ((*iter)->value, "foo");
81 EXPECT_LT((*iter)->index, 2u);
82 ++iter;
83 EXPECT_EQ((*iter)->value, "bar");
84 EXPECT_LT((*iter)->index, 2u);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080085}
86
87TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 StringPool::Ref ref = pool.makeRef("z");
91 StringPool::StyleRef ref2 = pool.makeRef(StyleString{{"a"}});
92 StringPool::Ref ref3 = pool.makeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080093
Adam Lesinskicacb28f2016-10-19 12:18:14 -070094 EXPECT_EQ(*ref, "z");
95 EXPECT_EQ(0u, ref.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080096
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 EXPECT_EQ(*(ref2->str), "a");
98 EXPECT_EQ(1u, ref2.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080099
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100 EXPECT_EQ(*ref3, "m");
101 EXPECT_EQ(2u, ref3.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800102
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
104 return a.value < b.value;
105 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800106
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700107 EXPECT_EQ(*ref, "z");
108 EXPECT_EQ(2u, ref.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800109
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 EXPECT_EQ(*(ref2->str), "a");
111 EXPECT_EQ(0u, ref2.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800112
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 EXPECT_EQ(*ref3, "m");
114 EXPECT_EQ(1u, ref3.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800115}
116
117TEST(StringPoolTest, SortAndStillDedupe) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700118 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800119
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700120 StringPool::Ref ref = pool.makeRef("z");
121 StringPool::Ref ref2 = pool.makeRef("a");
122 StringPool::Ref ref3 = pool.makeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800123
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
125 return a.value < b.value;
126 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800127
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 StringPool::Ref ref4 = pool.makeRef("z");
129 StringPool::Ref ref5 = pool.makeRef("a");
130 StringPool::Ref ref6 = pool.makeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800131
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 EXPECT_EQ(ref4.getIndex(), ref.getIndex());
133 EXPECT_EQ(ref5.getIndex(), ref2.getIndex());
134 EXPECT_EQ(ref6.getIndex(), ref3.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800135}
136
137TEST(StringPoolTest, AddStyles) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700138 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800139
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700140 StyleString str{{"android"}, {Span{{"b"}, 2, 6}}};
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700142 StringPool::StyleRef ref = pool.makeRef(str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800143
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 EXPECT_EQ(0u, ref.getIndex());
145 EXPECT_EQ(std::string("android"), *(ref->str));
146 ASSERT_EQ(1u, ref->spans.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800147
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700148 const StringPool::Span& span = ref->spans.front();
149 EXPECT_EQ(*(span.name), "b");
150 EXPECT_EQ(2u, span.firstChar);
151 EXPECT_EQ(6u, span.lastChar);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800152}
153
154TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800156
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 StringPool::Ref ref = pool.makeRef("android");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800158
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700159 StyleString str{{"android"}};
160 StringPool::StyleRef styleRef = pool.makeRef(str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800161
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 EXPECT_NE(ref.getIndex(), styleRef.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800163}
164
Adam Lesinski769de982015-04-10 19:43:55 -0700165TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700166 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700167
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 StringPool pool;
169 BigBuffer buffer(1024);
170 StringPool::flattenUtf8(&buffer, pool);
Adam Lesinski769de982015-04-10 19:43:55 -0700171
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700172 std::unique_ptr<uint8_t[]> data = util::copy(buffer);
173 ResStringPool test;
174 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski769de982015-04-10 19:43:55 -0700175}
176
Adam Lesinski52364f72016-01-11 13:10:24 -0800177TEST(StringPoolTest, FlattenOddCharactersUtf16) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700178 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700179
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700180 StringPool pool;
181 pool.makeRef("\u093f");
182 BigBuffer buffer(1024);
183 StringPool::flattenUtf16(&buffer, pool);
Adam Lesinski52364f72016-01-11 13:10:24 -0800184
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700185 std::unique_ptr<uint8_t[]> data = util::copy(buffer);
186 ResStringPool test;
187 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
188 size_t len = 0;
189 const char16_t* str = test.stringAt(0, &len);
190 EXPECT_EQ(1u, len);
191 EXPECT_EQ(u'\u093f', *str);
192 EXPECT_EQ(0u, str[1]);
Adam Lesinski52364f72016-01-11 13:10:24 -0800193}
194
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700195constexpr const char* sLongString =
196 "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑"
197 "え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限"
198 "します。メール、SMSや、同期を使 "
199 "用するその他のアプリは、起動しても更新されないことがあります。バッテリーセ"
200 "ーバーは端末の充電中は自動的にOFFになります。";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800201
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700202TEST(StringPoolTest, Flatten) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700203 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700204
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700205 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800206
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700207 StringPool::Ref ref1 = pool.makeRef("hello");
208 StringPool::Ref ref2 = pool.makeRef("goodbye");
209 StringPool::Ref ref3 = pool.makeRef(sLongString);
210 StringPool::Ref ref4 = pool.makeRef("");
211 StringPool::StyleRef ref5 = pool.makeRef(
212 StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800213
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214 EXPECT_EQ(0u, ref1.getIndex());
215 EXPECT_EQ(1u, ref2.getIndex());
216 EXPECT_EQ(2u, ref3.getIndex());
217 EXPECT_EQ(3u, ref4.getIndex());
218 EXPECT_EQ(4u, ref5.getIndex());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800219
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700220 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
221 StringPool::flattenUtf8(&buffers[0], pool);
222 StringPool::flattenUtf16(&buffers[1], pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800223
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700224 // Test both UTF-8 and UTF-16 buffers.
225 for (const BigBuffer& buffer : buffers) {
226 std::unique_ptr<uint8_t[]> data = util::copy(buffer);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700227
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700228 ResStringPool test;
229 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800230
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700231 EXPECT_EQ(std::string("hello"), util::getString(test, 0));
232 EXPECT_EQ(StringPiece16(u"hello"), util::getString16(test, 0));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700233
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700234 EXPECT_EQ(std::string("goodbye"), util::getString(test, 1));
235 EXPECT_EQ(StringPiece16(u"goodbye"), util::getString16(test, 1));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700236
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700237 EXPECT_EQ(StringPiece(sLongString), util::getString(test, 2));
238 EXPECT_EQ(util::utf8ToUtf16(sLongString),
239 util::getString16(test, 2).toString());
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700240
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 size_t len;
242 EXPECT_TRUE(test.stringAt(3, &len) != nullptr ||
243 test.string8At(3, &len) != nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700244
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700245 EXPECT_EQ(std::string("style"), util::getString(test, 4));
246 EXPECT_EQ(StringPiece16(u"style"), util::getString16(test, 4));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800247
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700248 const ResStringPool_span* span = test.styleAt(4);
249 ASSERT_NE(nullptr, span);
250 EXPECT_EQ(std::string("b"), util::getString(test, span->name.index));
251 EXPECT_EQ(StringPiece16(u"b"), util::getString16(test, span->name.index));
252 EXPECT_EQ(0u, span->firstChar);
253 EXPECT_EQ(1u, span->lastChar);
254 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800255
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700256 ASSERT_NE(ResStringPool_span::END, span->name.index);
257 EXPECT_EQ(std::string("i"), util::getString(test, span->name.index));
258 EXPECT_EQ(StringPiece16(u"i"), util::getString16(test, span->name.index));
259 EXPECT_EQ(2u, span->firstChar);
260 EXPECT_EQ(3u, span->lastChar);
261 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800262
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263 EXPECT_EQ(ResStringPool_span::END, span->name.index);
264 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800265}
266
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700267} // namespace aapt