blob: e1394fc0221f59d66881fa8882d5d73d6834d19b [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 Lesinskice5e56e2016-10-21 17:56:45 -070021#include "test/Test.h"
22#include "util/Util.h"
23
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080024namespace aapt {
25
26TEST(StringPoolTest, InsertOneString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070027 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080028
Adam Lesinskice5e56e2016-10-21 17:56:45 -070029 StringPool::Ref ref = pool.MakeRef("wut");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070030 EXPECT_EQ(*ref, "wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080031}
32
33TEST(StringPoolTest, InsertTwoUniqueStrings) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070034 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080035
Adam Lesinskice5e56e2016-10-21 17:56:45 -070036 StringPool::Ref ref = pool.MakeRef("wut");
37 StringPool::Ref ref2 = pool.MakeRef("hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080038
Adam Lesinskicacb28f2016-10-19 12:18:14 -070039 EXPECT_EQ(*ref, "wut");
40 EXPECT_EQ(*ref2, "hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080041}
42
43TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070044 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080045
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046 StringPool::Ref ref = pool.MakeRef("wut");
47 StringPool::Ref ref2 = pool.MakeRef("wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080048
Adam Lesinskicacb28f2016-10-19 12:18:14 -070049 EXPECT_EQ(*ref, "wut");
50 EXPECT_EQ(*ref2, "wut");
51 EXPECT_EQ(1u, pool.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080052}
53
54TEST(StringPoolTest, MaintainInsertionOrderIndex) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080056
Adam Lesinskice5e56e2016-10-21 17:56:45 -070057 StringPool::Ref ref = pool.MakeRef("z");
58 StringPool::Ref ref2 = pool.MakeRef("a");
59 StringPool::Ref ref3 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080060
Adam Lesinskice5e56e2016-10-21 17:56:45 -070061 EXPECT_EQ(0u, ref.index());
62 EXPECT_EQ(1u, ref2.index());
63 EXPECT_EQ(2u, ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080064}
65
66TEST(StringPoolTest, PruneStringsWithNoReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080068
Adam Lesinskice5e56e2016-10-21 17:56:45 -070069 StringPool::Ref refA = pool.MakeRef("foo");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070070 {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070071 StringPool::Ref ref = pool.MakeRef("wut");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 EXPECT_EQ(*ref, "wut");
Adam Lesinski1ab598f2015-08-14 14:26:04 -070073 EXPECT_EQ(2u, pool.size());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070074 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070075 StringPool::Ref refB = pool.MakeRef("bar");
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076
77 EXPECT_EQ(3u, pool.size());
Adam Lesinskice5e56e2016-10-21 17:56:45 -070078 pool.Prune();
Adam Lesinskicacb28f2016-10-19 12:18:14 -070079 EXPECT_EQ(2u, pool.size());
80 StringPool::const_iterator iter = begin(pool);
81 EXPECT_EQ((*iter)->value, "foo");
82 EXPECT_LT((*iter)->index, 2u);
83 ++iter;
84 EXPECT_EQ((*iter)->value, "bar");
85 EXPECT_LT((*iter)->index, 2u);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080086}
87
88TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070089 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080090
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 StringPool::Ref ref = pool.MakeRef("z");
92 StringPool::StyleRef ref2 = pool.MakeRef(StyleString{{"a"}});
93 StringPool::Ref ref3 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080094
Adam Lesinskicacb28f2016-10-19 12:18:14 -070095 EXPECT_EQ(*ref, "z");
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096 EXPECT_EQ(0u, ref.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080097
Adam Lesinskicacb28f2016-10-19 12:18:14 -070098 EXPECT_EQ(*(ref2->str), "a");
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099 EXPECT_EQ(1u, ref2.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800100
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 EXPECT_EQ(*ref3, "m");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700102 EXPECT_EQ(2u, ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800103
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104 pool.Sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 return a.value < b.value;
106 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800107
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700108 EXPECT_EQ(*ref, "z");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 EXPECT_EQ(2u, ref.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800110
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700111 EXPECT_EQ(*(ref2->str), "a");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 EXPECT_EQ(0u, ref2.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800113
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700114 EXPECT_EQ(*ref3, "m");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 EXPECT_EQ(1u, ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800116}
117
118TEST(StringPoolTest, SortAndStillDedupe) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800120
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700121 StringPool::Ref ref = pool.MakeRef("z");
122 StringPool::Ref ref2 = pool.MakeRef("a");
123 StringPool::Ref ref3 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800124
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 pool.Sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126 return a.value < b.value;
127 });
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800128
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700129 StringPool::Ref ref4 = pool.MakeRef("z");
130 StringPool::Ref ref5 = pool.MakeRef("a");
131 StringPool::Ref ref6 = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800132
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700133 EXPECT_EQ(ref4.index(), ref.index());
134 EXPECT_EQ(ref5.index(), ref2.index());
135 EXPECT_EQ(ref6.index(), ref3.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800136}
137
138TEST(StringPoolTest, AddStyles) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800140
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 StyleString str{{"android"}, {Span{{"b"}, 2, 6}}};
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800142
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 StringPool::StyleRef ref = pool.MakeRef(str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800144
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700145 EXPECT_EQ(0u, ref.index());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 EXPECT_EQ(std::string("android"), *(ref->str));
147 ASSERT_EQ(1u, ref->spans.size());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800148
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149 const StringPool::Span& span = ref->spans.front();
150 EXPECT_EQ(*(span.name), "b");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700151 EXPECT_EQ(2u, span.first_char);
152 EXPECT_EQ(6u, span.last_char);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800153}
154
155TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700156 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800157
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158 StringPool::Ref ref = pool.MakeRef("android");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800159
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 StyleString str{{"android"}};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 StringPool::StyleRef styleRef = pool.MakeRef(str);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800162
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 EXPECT_NE(ref.index(), styleRef.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800164}
165
Adam Lesinski769de982015-04-10 19:43:55 -0700166TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700168
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700169 StringPool pool;
170 BigBuffer buffer(1024);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700171 StringPool::FlattenUtf8(&buffer, pool);
Adam Lesinski769de982015-04-10 19:43:55 -0700172
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700173 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700174 ResStringPool test;
175 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski769de982015-04-10 19:43:55 -0700176}
177
Adam Lesinski52364f72016-01-11 13:10:24 -0800178TEST(StringPoolTest, FlattenOddCharactersUtf16) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700180
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700181 StringPool pool;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 pool.MakeRef("\u093f");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 BigBuffer buffer(1024);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 StringPool::FlattenUtf16(&buffer, pool);
Adam Lesinski52364f72016-01-11 13:10:24 -0800185
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700186 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700187 ResStringPool test;
188 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
189 size_t len = 0;
190 const char16_t* str = test.stringAt(0, &len);
191 EXPECT_EQ(1u, len);
192 EXPECT_EQ(u'\u093f', *str);
193 EXPECT_EQ(0u, str[1]);
Adam Lesinski52364f72016-01-11 13:10:24 -0800194}
195
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700196constexpr const char* sLongString =
197 "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑"
198 "え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限"
199 "します。メール、SMSや、同期を使 "
200 "用するその他のアプリは、起動しても更新されないことがあります。バッテリーセ"
201 "ーバーは端末の充電中は自動的にOFFになります。";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800202
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700203TEST(StringPoolTest, Flatten) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 using namespace android; // For NO_ERROR on Windows.
Adam Lesinski803c7c82016-04-06 16:09:43 -0700205
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700206 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800207
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 StringPool::Ref ref1 = pool.MakeRef("hello");
209 StringPool::Ref ref2 = pool.MakeRef("goodbye");
210 StringPool::Ref ref3 = pool.MakeRef(sLongString);
211 StringPool::Ref ref4 = pool.MakeRef("");
212 StringPool::StyleRef ref5 = pool.MakeRef(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700213 StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800214
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700215 EXPECT_EQ(0u, ref1.index());
216 EXPECT_EQ(1u, ref2.index());
217 EXPECT_EQ(2u, ref3.index());
218 EXPECT_EQ(3u, ref4.index());
219 EXPECT_EQ(4u, ref5.index());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800220
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700221 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700222 StringPool::FlattenUtf8(&buffers[0], pool);
223 StringPool::FlattenUtf16(&buffers[1], pool);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800224
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700225 // Test both UTF-8 and UTF-16 buffers.
226 for (const BigBuffer& buffer : buffers) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700228
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 ResStringPool test;
230 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800231
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 EXPECT_EQ(std::string("hello"), util::GetString(test, 0));
233 EXPECT_EQ(StringPiece16(u"hello"), util::GetString16(test, 0));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700234
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 EXPECT_EQ(std::string("goodbye"), util::GetString(test, 1));
236 EXPECT_EQ(StringPiece16(u"goodbye"), util::GetString16(test, 1));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700237
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700238 EXPECT_EQ(StringPiece(sLongString), util::GetString(test, 2));
239 EXPECT_EQ(util::Utf8ToUtf16(sLongString),
240 util::GetString16(test, 2).ToString());
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700241
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700242 size_t len;
243 EXPECT_TRUE(test.stringAt(3, &len) != nullptr ||
244 test.string8At(3, &len) != nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700245
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700246 EXPECT_EQ(std::string("style"), util::GetString(test, 4));
247 EXPECT_EQ(StringPiece16(u"style"), util::GetString16(test, 4));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800248
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 const ResStringPool_span* span = test.styleAt(4);
250 ASSERT_NE(nullptr, span);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700251 EXPECT_EQ(std::string("b"), util::GetString(test, span->name.index));
252 EXPECT_EQ(StringPiece16(u"b"), util::GetString16(test, span->name.index));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700253 EXPECT_EQ(0u, span->firstChar);
254 EXPECT_EQ(1u, span->lastChar);
255 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800256
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 ASSERT_NE(ResStringPool_span::END, span->name.index);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 EXPECT_EQ(std::string("i"), util::GetString(test, span->name.index));
259 EXPECT_EQ(StringPiece16(u"i"), util::GetString16(test, span->name.index));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260 EXPECT_EQ(2u, span->firstChar);
261 EXPECT_EQ(3u, span->lastChar);
262 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800263
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264 EXPECT_EQ(ResStringPool_span::END, span->name.index);
265 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800266}
267
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268} // namespace aapt