StringPool_test.cpp revision 6f6ceb7e1456698b1f33e04536bfb3227f9fcfcb
1/*
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"
18#include "Util.h"
19
20#include <gtest/gtest.h>
21#include <string>
22
23namespace aapt {
24
25TEST(StringPoolTest, InsertOneString) {
26    StringPool pool;
27
28    StringPool::Ref ref = pool.makeRef(u"wut");
29    EXPECT_EQ(*ref, u"wut");
30}
31
32TEST(StringPoolTest, InsertTwoUniqueStrings) {
33    StringPool pool;
34
35    StringPool::Ref ref = pool.makeRef(u"wut");
36    StringPool::Ref ref2 = pool.makeRef(u"hey");
37
38    EXPECT_EQ(*ref, u"wut");
39    EXPECT_EQ(*ref2, u"hey");
40}
41
42TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
43    StringPool pool;
44
45    StringPool::Ref ref = pool.makeRef(u"wut");
46    StringPool::Ref ref2 = pool.makeRef(u"wut");
47
48    EXPECT_EQ(*ref, u"wut");
49    EXPECT_EQ(*ref2, u"wut");
50    EXPECT_EQ(1u, pool.size());
51}
52
53TEST(StringPoolTest, MaintainInsertionOrderIndex) {
54    StringPool pool;
55
56    StringPool::Ref ref = pool.makeRef(u"z");
57    StringPool::Ref ref2 = pool.makeRef(u"a");
58    StringPool::Ref ref3 = pool.makeRef(u"m");
59
60    EXPECT_EQ(0u, ref.getIndex());
61    EXPECT_EQ(1u, ref2.getIndex());
62    EXPECT_EQ(2u, ref3.getIndex());
63}
64
65TEST(StringPoolTest, PruneStringsWithNoReferences) {
66    StringPool pool;
67
68    {
69        StringPool::Ref ref = pool.makeRef(u"wut");
70        EXPECT_EQ(*ref, u"wut");
71        EXPECT_EQ(1u, pool.size());
72    }
73
74    EXPECT_EQ(1u, pool.size());
75    pool.prune();
76    EXPECT_EQ(0u, pool.size());
77}
78
79TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
80    StringPool pool;
81
82    StringPool::Ref ref = pool.makeRef(u"z");
83    StringPool::StyleRef ref2 = pool.makeRef(StyleString{ {u"a"} });
84    StringPool::Ref ref3 = pool.makeRef(u"m");
85
86    EXPECT_EQ(*ref, u"z");
87    EXPECT_EQ(0u, ref.getIndex());
88
89    EXPECT_EQ(*(ref2->str), u"a");
90    EXPECT_EQ(1u, ref2.getIndex());
91
92    EXPECT_EQ(*ref3, u"m");
93    EXPECT_EQ(2u, ref3.getIndex());
94
95    pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
96        return a.value < b.value;
97    });
98
99
100    EXPECT_EQ(*ref, u"z");
101    EXPECT_EQ(2u, ref.getIndex());
102
103    EXPECT_EQ(*(ref2->str), u"a");
104    EXPECT_EQ(0u, ref2.getIndex());
105
106    EXPECT_EQ(*ref3, u"m");
107    EXPECT_EQ(1u, ref3.getIndex());
108}
109
110TEST(StringPoolTest, SortAndStillDedupe) {
111    StringPool pool;
112
113    StringPool::Ref ref = pool.makeRef(u"z");
114    StringPool::Ref ref2 = pool.makeRef(u"a");
115    StringPool::Ref ref3 = pool.makeRef(u"m");
116
117    pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
118        return a.value < b.value;
119    });
120
121    StringPool::Ref ref4 = pool.makeRef(u"z");
122    StringPool::Ref ref5 = pool.makeRef(u"a");
123    StringPool::Ref ref6 = pool.makeRef(u"m");
124
125    EXPECT_EQ(ref4.getIndex(), ref.getIndex());
126    EXPECT_EQ(ref5.getIndex(), ref2.getIndex());
127    EXPECT_EQ(ref6.getIndex(), ref3.getIndex());
128}
129
130TEST(StringPoolTest, AddStyles) {
131    StringPool pool;
132
133    StyleString str {
134        { u"android" },
135        {
136            Span{ { u"b" }, 2, 6 }
137        }
138    };
139
140    StringPool::StyleRef ref = pool.makeRef(str);
141
142    EXPECT_EQ(0u, ref.getIndex());
143    EXPECT_EQ(std::u16string(u"android"), *(ref->str));
144    ASSERT_EQ(1u, ref->spans.size());
145
146    const StringPool::Span& span = ref->spans.front();
147    EXPECT_EQ(*(span.name), u"b");
148    EXPECT_EQ(2u, span.firstChar);
149    EXPECT_EQ(6u, span.lastChar);
150}
151
152TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
153    StringPool pool;
154
155    StringPool::Ref ref = pool.makeRef(u"android");
156
157    StyleString str { { u"android" } };
158    StringPool::StyleRef styleRef = pool.makeRef(str);
159
160    EXPECT_NE(ref.getIndex(), styleRef.getIndex());
161}
162
163constexpr const char16_t* sLongString = u"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使 用するその他のアプリは、起動しても更新されないことがあります。バッテリーセーバーは端末の充電中は自動的にOFFになります。";
164
165TEST(StringPoolTest, FlattenUtf8) {
166    StringPool pool;
167
168    StringPool::Ref ref1 = pool.makeRef(u"hello");
169    StringPool::Ref ref2 = pool.makeRef(u"goodbye");
170    StringPool::Ref ref3 = pool.makeRef(sLongString);
171    StringPool::StyleRef ref4 = pool.makeRef(StyleString{
172            { u"style" },
173            { Span{ { u"b" }, 0, 1 }, Span{ { u"i" }, 2, 3 } }
174    });
175
176    EXPECT_EQ(0u, ref1.getIndex());
177    EXPECT_EQ(1u, ref2.getIndex());
178    EXPECT_EQ(2u, ref3.getIndex());
179    EXPECT_EQ(3u, ref4.getIndex());
180
181    BigBuffer buffer(1024);
182    StringPool::flattenUtf8(&buffer, pool);
183
184    uint8_t* data = new uint8_t[buffer.size()];
185    uint8_t* p = data;
186    for (const auto& b : buffer) {
187        memcpy(p, b.buffer.get(), b.size);
188        p += b.size;
189    }
190
191    {
192        android::ResStringPool test;
193        ASSERT_EQ(android::NO_ERROR, test.setTo(data, buffer.size()));
194
195        EXPECT_EQ(util::getString(test, 0), u"hello");
196        EXPECT_EQ(util::getString(test, 1), u"goodbye");
197        EXPECT_EQ(util::getString(test, 2), sLongString);
198        EXPECT_EQ(util::getString(test, 3), u"style");
199
200        const android::ResStringPool_span* span = test.styleAt(3);
201        ASSERT_NE(nullptr, span);
202        EXPECT_EQ(util::getString(test, span->name.index), u"b");
203        EXPECT_EQ(0u, span->firstChar);
204        EXPECT_EQ(1u, span->lastChar);
205        span++;
206
207        ASSERT_NE(android::ResStringPool_span::END, span->name.index);
208        EXPECT_EQ(util::getString(test, span->name.index), u"i");
209        EXPECT_EQ(2u, span->firstChar);
210        EXPECT_EQ(3u, span->lastChar);
211        span++;
212
213        EXPECT_EQ(android::ResStringPool_span::END, span->name.index);
214    }
215    delete[] data;
216}
217
218} // namespace aapt
219