blob: 648be7d337542e51959ee0dd9b82b2073969c7e5 [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
Ryan Mitchell70414f22018-03-26 11:05:31 -070023#include "Diagnostics.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070024#include "test/Test.h"
25#include "util/Util.h"
26
Adam Lesinski060b53d2017-07-28 17:10:35 -070027using ::android::StringPiece;
28using ::android::StringPiece16;
29using ::testing::Eq;
30using ::testing::Ne;
31using ::testing::NotNull;
32using ::testing::Pointee;
Adam Lesinskid5083f62017-01-16 15:07:21 -080033
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080034namespace aapt {
35
36TEST(StringPoolTest, InsertOneString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070037 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080038
Adam Lesinskice5e56e2016-10-21 17:56:45 -070039 StringPool::Ref ref = pool.MakeRef("wut");
Adam Lesinski060b53d2017-07-28 17:10:35 -070040 EXPECT_THAT(*ref, Eq("wut"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080041}
42
43TEST(StringPoolTest, InsertTwoUniqueStrings) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070044 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080045
Adam Lesinski060b53d2017-07-28 17:10:35 -070046 StringPool::Ref ref_a = pool.MakeRef("wut");
47 StringPool::Ref ref_b = pool.MakeRef("hey");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080048
Adam Lesinski060b53d2017-07-28 17:10:35 -070049 EXPECT_THAT(*ref_a, Eq("wut"));
50 EXPECT_THAT(*ref_b, Eq("hey"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080051}
52
53TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070054 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080055
Adam Lesinski060b53d2017-07-28 17:10:35 -070056 StringPool::Ref ref_a = pool.MakeRef("wut");
57 StringPool::Ref ref_b = pool.MakeRef("wut");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080058
Adam Lesinski060b53d2017-07-28 17:10:35 -070059 EXPECT_THAT(*ref_a, Eq("wut"));
60 EXPECT_THAT(*ref_b, Eq("wut"));
61 EXPECT_THAT(pool.size(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080062}
63
y46029262018-04-16 18:13:14 -070064TEST(StringPoolTest, DoNotDedupeSameStringDifferentPriority) {
65 StringPool pool;
66
67 StringPool::Ref ref_a = pool.MakeRef("wut", StringPool::Context(0x81010001));
68 StringPool::Ref ref_b = pool.MakeRef("wut", StringPool::Context(0x81010002));
69
70 EXPECT_THAT(*ref_a, Eq("wut"));
71 EXPECT_THAT(*ref_b, Eq("wut"));
72 EXPECT_THAT(pool.size(), Eq(2u));
73}
74
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080075TEST(StringPoolTest, MaintainInsertionOrderIndex) {
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("z");
79 StringPool::Ref ref_b = pool.MakeRef("a");
80 StringPool::Ref ref_c = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080081
Adam Lesinski060b53d2017-07-28 17:10:35 -070082 EXPECT_THAT(ref_a.index(), Eq(0u));
83 EXPECT_THAT(ref_b.index(), Eq(1u));
84 EXPECT_THAT(ref_c.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080085}
86
Ryan Mitchell4e9a9222018-11-13 10:40:07 -080087TEST(StringPoolTest, AssignStringIndex) {
88 StringPool pool;
89
90 StringPool::Ref ref_a = pool.MakeRef("0", StringPool::Context{}, 0u);
91 StringPool::Ref ref_b = pool.MakeRef("1", StringPool::Context{}, 1u);
92 StringPool::Ref ref_c = pool.MakeRef("5", StringPool::Context{}, 5u);
93 StringPool::Ref ref_d = pool.MakeRef("2", StringPool::Context{}, 2u);
94 StringPool::Ref ref_e = pool.MakeRef("4", StringPool::Context{}, 4u);
95 StringPool::Ref ref_f = pool.MakeRef("3", StringPool::Context{}, 3u);
96
97 EXPECT_THAT(ref_a.index(), Eq(0u));
98 EXPECT_THAT(ref_b.index(), Eq(1u));
99 EXPECT_THAT(ref_d.index(), Eq(2u));
100 EXPECT_THAT(ref_f.index(), Eq(3u));
101 EXPECT_THAT(ref_e.index(), Eq(4u));
102 EXPECT_THAT(ref_c.index(), Eq(5u));
103}
104
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800105TEST(StringPoolTest, PruneStringsWithNoReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700106 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800107
Adam Lesinski060b53d2017-07-28 17:10:35 -0700108 StringPool::Ref ref_a = pool.MakeRef("foo");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700109
Adam Lesinski060b53d2017-07-28 17:10:35 -0700110 {
111 StringPool::Ref ref_b = pool.MakeRef("wut");
112 EXPECT_THAT(*ref_b, Eq("wut"));
113 EXPECT_THAT(pool.size(), Eq(2u));
114 pool.Prune();
115 EXPECT_THAT(pool.size(), Eq(2u));
116 }
117 EXPECT_THAT(pool.size(), Eq(2u));
118
119 {
120 StringPool::Ref ref_c = pool.MakeRef("bar");
121 EXPECT_THAT(pool.size(), Eq(3u));
122
123 pool.Prune();
124 EXPECT_THAT(pool.size(), Eq(2u));
125 }
126 EXPECT_THAT(pool.size(), Eq(2u));
127
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 pool.Prune();
Adam Lesinski060b53d2017-07-28 17:10:35 -0700129 EXPECT_THAT(pool.size(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800130}
131
Adam Lesinski060b53d2017-07-28 17:10:35 -0700132TEST(StringPoolTest, SortAndMaintainIndexesInStringReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700133 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800134
Adam Lesinski060b53d2017-07-28 17:10:35 -0700135 StringPool::Ref ref_a = pool.MakeRef("z");
136 StringPool::Ref ref_b = pool.MakeRef("a");
137 StringPool::Ref ref_c = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800138
Adam Lesinski060b53d2017-07-28 17:10:35 -0700139 EXPECT_THAT(*ref_a, Eq("z"));
140 EXPECT_THAT(ref_a.index(), Eq(0u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141
Adam Lesinski060b53d2017-07-28 17:10:35 -0700142 EXPECT_THAT(*ref_b, Eq("a"));
143 EXPECT_THAT(ref_b.index(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800144
Adam Lesinski060b53d2017-07-28 17:10:35 -0700145 EXPECT_THAT(*ref_c, Eq("m"));
146 EXPECT_THAT(ref_c.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800147
Adam Lesinski060b53d2017-07-28 17:10:35 -0700148 pool.Sort();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800149
Adam Lesinski060b53d2017-07-28 17:10:35 -0700150 EXPECT_THAT(*ref_a, Eq("z"));
151 EXPECT_THAT(ref_a.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800152
Adam Lesinski060b53d2017-07-28 17:10:35 -0700153 EXPECT_THAT(*ref_b, Eq("a"));
154 EXPECT_THAT(ref_b.index(), Eq(0u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800155
Adam Lesinski060b53d2017-07-28 17:10:35 -0700156 EXPECT_THAT(*ref_c, Eq("m"));
157 EXPECT_THAT(ref_c.index(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800158}
159
160TEST(StringPoolTest, SortAndStillDedupe) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700161 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800162
Adam Lesinski060b53d2017-07-28 17:10:35 -0700163 StringPool::Ref ref_a = pool.MakeRef("z");
164 StringPool::Ref ref_b = pool.MakeRef("a");
165 StringPool::Ref ref_c = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800166
Adam Lesinski060b53d2017-07-28 17:10:35 -0700167 pool.Sort();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800168
Adam Lesinski060b53d2017-07-28 17:10:35 -0700169 StringPool::Ref ref_d = pool.MakeRef("z");
170 StringPool::Ref ref_e = pool.MakeRef("a");
171 StringPool::Ref ref_f = pool.MakeRef("m");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800172
Adam Lesinski060b53d2017-07-28 17:10:35 -0700173 EXPECT_THAT(ref_d.index(), Eq(ref_a.index()));
174 EXPECT_THAT(ref_e.index(), Eq(ref_b.index()));
175 EXPECT_THAT(ref_f.index(), Eq(ref_c.index()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800176}
177
178TEST(StringPoolTest, AddStyles) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800180
Adam Lesinski060b53d2017-07-28 17:10:35 -0700181 StringPool::StyleRef ref = pool.MakeRef(StyleString{{"android"}, {Span{{"b"}, 2, 6}}});
182 EXPECT_THAT(ref.index(), Eq(0u));
183 EXPECT_THAT(ref->value, Eq("android"));
184 ASSERT_THAT(ref->spans.size(), Eq(1u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800185
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 const StringPool::Span& span = ref->spans.front();
Adam Lesinski060b53d2017-07-28 17:10:35 -0700187 EXPECT_THAT(*span.name, Eq("b"));
188 EXPECT_THAT(span.first_char, Eq(2u));
189 EXPECT_THAT(span.last_char, Eq(6u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800190}
191
192TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700193 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800194
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700195 StringPool::Ref ref = pool.MakeRef("android");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800196
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700197 StyleString str{{"android"}};
Adam Lesinski060b53d2017-07-28 17:10:35 -0700198 StringPool::StyleRef style_ref = pool.MakeRef(StyleString{{"android"}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800199
Adam Lesinski060b53d2017-07-28 17:10:35 -0700200 EXPECT_THAT(ref.index(), Ne(style_ref.index()));
201}
202
203TEST(StringPoolTest, StylesAndStringsAreSeparateAfterSorting) {
204 StringPool pool;
205
206 StringPool::StyleRef ref_a = pool.MakeRef(StyleString{{"beta"}});
207 StringPool::Ref ref_b = pool.MakeRef("alpha");
208 StringPool::StyleRef ref_c = pool.MakeRef(StyleString{{"alpha"}});
209
210 EXPECT_THAT(ref_b.index(), Ne(ref_c.index()));
211
212 pool.Sort();
213
214 EXPECT_THAT(ref_c.index(), Eq(0u));
215 EXPECT_THAT(ref_a.index(), Eq(1u));
216 EXPECT_THAT(ref_b.index(), Eq(2u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800217}
218
Adam Lesinski769de982015-04-10 19:43:55 -0700219TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700220 using namespace android; // For NO_ERROR on Windows.
Ryan Mitchell70414f22018-03-26 11:05:31 -0700221 StdErrDiagnostics diag;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700222
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700223 StringPool pool;
224 BigBuffer buffer(1024);
Ryan Mitchell70414f22018-03-26 11:05:31 -0700225 StringPool::FlattenUtf8(&buffer, pool, &diag);
Adam Lesinski769de982015-04-10 19:43:55 -0700226
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700228 ResStringPool test;
Adam Lesinski060b53d2017-07-28 17:10:35 -0700229 ASSERT_THAT(test.setTo(data.get(), buffer.size()), Eq(NO_ERROR));
Adam Lesinski769de982015-04-10 19:43:55 -0700230}
231
Adam Lesinski52364f72016-01-11 13:10:24 -0800232TEST(StringPoolTest, FlattenOddCharactersUtf16) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 using namespace android; // For NO_ERROR on Windows.
Ryan Mitchell70414f22018-03-26 11:05:31 -0700234 StdErrDiagnostics diag;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700235
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700236 StringPool pool;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237 pool.MakeRef("\u093f");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700238 BigBuffer buffer(1024);
Ryan Mitchell70414f22018-03-26 11:05:31 -0700239 StringPool::FlattenUtf16(&buffer, pool, &diag);
Adam Lesinski52364f72016-01-11 13:10:24 -0800240
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700241 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700242 ResStringPool test;
243 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
244 size_t len = 0;
245 const char16_t* str = test.stringAt(0, &len);
Adam Lesinski060b53d2017-07-28 17:10:35 -0700246 EXPECT_THAT(len, Eq(1u));
247 EXPECT_THAT(str, Pointee(Eq(u'\u093f')));
248 EXPECT_THAT(str[1], Eq(0u));
Adam Lesinski52364f72016-01-11 13:10:24 -0800249}
250
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700251constexpr const char* sLongString =
252 "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑"
253 "え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限"
254 "します。メール、SMSや、同期を使 "
255 "用するその他のアプリは、起動しても更新されないことがあります。バッテリーセ"
256 "ーバーは端末の充電中は自動的にOFFになります。";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800257
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700258TEST(StringPoolTest, Flatten) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700259 using namespace android; // For NO_ERROR on Windows.
Ryan Mitchell70414f22018-03-26 11:05:31 -0700260 StdErrDiagnostics diag;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700261
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700262 StringPool pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800263
Adam Lesinski060b53d2017-07-28 17:10:35 -0700264 StringPool::Ref ref_a = pool.MakeRef("hello");
265 StringPool::Ref ref_b = pool.MakeRef("goodbye");
266 StringPool::Ref ref_c = pool.MakeRef(sLongString);
267 StringPool::Ref ref_d = pool.MakeRef("");
268 StringPool::StyleRef ref_e =
269 pool.MakeRef(StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800270
Adam Lesinski060b53d2017-07-28 17:10:35 -0700271 // Styles are always first.
272 EXPECT_THAT(ref_e.index(), Eq(0u));
273
274 EXPECT_THAT(ref_a.index(), Eq(1u));
275 EXPECT_THAT(ref_b.index(), Eq(2u));
276 EXPECT_THAT(ref_c.index(), Eq(3u));
277 EXPECT_THAT(ref_d.index(), Eq(4u));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800278
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700279 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
Ryan Mitchell70414f22018-03-26 11:05:31 -0700280 StringPool::FlattenUtf8(&buffers[0], pool, &diag);
281 StringPool::FlattenUtf16(&buffers[1], pool, &diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800282
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700283 // Test both UTF-8 and UTF-16 buffers.
284 for (const BigBuffer& buffer : buffers) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700285 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700286
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 ResStringPool test;
288 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800289
Adam Lesinski060b53d2017-07-28 17:10:35 -0700290 EXPECT_THAT(util::GetString(test, 1), Eq("hello"));
291 EXPECT_THAT(util::GetString16(test, 1), Eq(u"hello"));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700292
Adam Lesinski060b53d2017-07-28 17:10:35 -0700293 EXPECT_THAT(util::GetString(test, 2), Eq("goodbye"));
294 EXPECT_THAT(util::GetString16(test, 2), Eq(u"goodbye"));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700295
Adam Lesinski060b53d2017-07-28 17:10:35 -0700296 EXPECT_THAT(util::GetString(test, 3), Eq(sLongString));
297 EXPECT_THAT(util::GetString16(test, 3), Eq(util::Utf8ToUtf16(sLongString)));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700298
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700299 size_t len;
Adam Lesinski060b53d2017-07-28 17:10:35 -0700300 EXPECT_TRUE(test.stringAt(4, &len) != nullptr || test.string8At(4, &len) != nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700301
Adam Lesinski060b53d2017-07-28 17:10:35 -0700302 EXPECT_THAT(util::GetString(test, 0), Eq("style"));
303 EXPECT_THAT(util::GetString16(test, 0), Eq(u"style"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800304
Adam Lesinski060b53d2017-07-28 17:10:35 -0700305 const ResStringPool_span* span = test.styleAt(0);
306 ASSERT_THAT(span, NotNull());
307 EXPECT_THAT(util::GetString(test, span->name.index), Eq("b"));
308 EXPECT_THAT(util::GetString16(test, span->name.index), Eq(u"b"));
309 EXPECT_THAT(span->firstChar, Eq(0u));
310 EXPECT_THAT(span->lastChar, Eq(1u));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700311 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800312
Adam Lesinski060b53d2017-07-28 17:10:35 -0700313 ASSERT_THAT(span->name.index, Ne(ResStringPool_span::END));
314 EXPECT_THAT(util::GetString(test, span->name.index), Eq("i"));
315 EXPECT_THAT(util::GetString16(test, span->name.index), Eq(u"i"));
316 EXPECT_THAT(span->firstChar, Eq(2u));
317 EXPECT_THAT(span->lastChar, Eq(3u));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700318 span++;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800319
Adam Lesinski060b53d2017-07-28 17:10:35 -0700320 EXPECT_THAT(span->name.index, Eq(ResStringPool_span::END));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700321 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800322}
323
Ryan Mitchell4353d61b2018-09-10 17:09:12 -0700324TEST(StringPoolTest, ModifiedUTF8) {
Ryan Mitchelld86ea582018-06-27 11:57:18 -0700325 using namespace android; // For NO_ERROR on Windows.
326 StdErrDiagnostics diag;
327 StringPool pool;
328 StringPool::Ref ref_a = pool.MakeRef("\xF0\x90\x90\x80"); // 𐐀 (U+10400)
329 StringPool::Ref ref_b = pool.MakeRef("foo \xF0\x90\x90\xB7 bar"); // 𐐷 (U+10437)
330 StringPool::Ref ref_c = pool.MakeRef("\xF0\x90\x90\x80\xF0\x90\x90\xB7");
331
332 BigBuffer buffer(1024);
333 StringPool::FlattenUtf8(&buffer, pool, &diag);
334 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
335
Ryan Mitchell4353d61b2018-09-10 17:09:12 -0700336 // Check that the codepoints are encoded using two three-byte surrogate pairs
Ryan Mitchelld86ea582018-06-27 11:57:18 -0700337 ResStringPool test;
338 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
Ryan Mitchell4353d61b2018-09-10 17:09:12 -0700339 size_t len;
340 const char* str = test.string8At(0, &len);
341 ASSERT_THAT(str, NotNull());
342 EXPECT_THAT(std::string(str, len), Eq("\xED\xA0\x81\xED\xB0\x80"));
343 str = test.string8At(1, &len);
344 ASSERT_THAT(str, NotNull());
345 EXPECT_THAT(std::string(str, len), Eq("foo \xED\xA0\x81\xED\xB0\xB7 bar"));
346 str = test.string8At(2, &len);
347 ASSERT_THAT(str, NotNull());
348 EXPECT_THAT(std::string(str, len), Eq("\xED\xA0\x81\xED\xB0\x80\xED\xA0\x81\xED\xB0\xB7"));
349
350 // Check that retrieving the strings returns the original UTF-8 character bytes
351 EXPECT_THAT(util::GetString(test, 0), Eq("\xF0\x90\x90\x80"));
352 EXPECT_THAT(util::GetString(test, 1), Eq("foo \xF0\x90\x90\xB7 bar"));
353 EXPECT_THAT(util::GetString(test, 2), Eq("\xF0\x90\x90\x80\xF0\x90\x90\xB7"));
Ryan Mitchelld86ea582018-06-27 11:57:18 -0700354}
Ryan Mitchell61ffd402018-04-16 18:21:14 +0000355
Ryan Mitchell70414f22018-03-26 11:05:31 -0700356TEST(StringPoolTest, MaxEncodingLength) {
357 StdErrDiagnostics diag;
358 using namespace android; // For NO_ERROR on Windows.
359 ResStringPool test;
360
361 StringPool pool;
362 pool.MakeRef("aaaaaaaaaa");
363 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)};
364
365 // Make sure a UTF-8 string under the maximum length does not produce an error
366 EXPECT_THAT(StringPool::FlattenUtf8(&buffers[0], pool, &diag), Eq(true));
367 std::unique_ptr<uint8_t[]> data = util::Copy(buffers[0]);
368 test.setTo(data.get(), buffers[0].size());
369 EXPECT_THAT(util::GetString(test, 0), Eq("aaaaaaaaaa"));
370
371 // Make sure a UTF-16 string under the maximum length does not produce an error
372 EXPECT_THAT(StringPool::FlattenUtf16(&buffers[1], pool, &diag), Eq(true));
373 data = util::Copy(buffers[1]);
374 test.setTo(data.get(), buffers[1].size());
375 EXPECT_THAT(util::GetString16(test, 0), Eq(u"aaaaaaaaaa"));
376
377 StringPool pool2;
378 std::string longStr(50000, 'a');
379 pool2.MakeRef("this fits1");
380 pool2.MakeRef(longStr);
381 pool2.MakeRef("this fits2");
382 BigBuffer buffers2[2] = {BigBuffer(1024), BigBuffer(1024)};
383
384 // Make sure a string that exceeds the maximum length of UTF-8 produces an
385 // error and writes a shorter error string instead
386 EXPECT_THAT(StringPool::FlattenUtf8(&buffers2[0], pool2, &diag), Eq(false));
387 data = util::Copy(buffers2[0]);
388 test.setTo(data.get(), buffers2[0].size());
389 EXPECT_THAT(util::GetString(test, 0), "this fits1");
390 EXPECT_THAT(util::GetString(test, 1), "STRING_TOO_LARGE");
391 EXPECT_THAT(util::GetString(test, 2), "this fits2");
392
393 // Make sure a string that a string that exceeds the maximum length of UTF-8
394 // but not UTF-16 does not error for UTF-16
395 StringPool pool3;
396 std::u16string longStr16(50000, 'a');
397 pool3.MakeRef(longStr);
398 EXPECT_THAT(StringPool::FlattenUtf16(&buffers2[1], pool3, &diag), Eq(true));
399 data = util::Copy(buffers2[1]);
400 test.setTo(data.get(), buffers2[1].size());
401 EXPECT_THAT(util::GetString16(test, 0), Eq(longStr16));
402}
403
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700404} // namespace aapt