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