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 19 #include <string> 20 21 #include "androidfw/StringPiece.h" 22 23 #include "test/Test.h" 24 #include "util/Util.h" 25 26 using ::android::StringPiece; 27 using ::android::StringPiece16; 28 using ::testing::Eq; 29 using ::testing::Ne; 30 using ::testing::NotNull; 31 using ::testing::Pointee; 32 33 namespace aapt { 34 35 TEST(StringPoolTest, InsertOneString) { 36 StringPool pool; 37 38 StringPool::Ref ref = pool.MakeRef("wut"); 39 EXPECT_THAT(*ref, Eq("wut")); 40 } 41 42 TEST(StringPoolTest, InsertTwoUniqueStrings) { 43 StringPool pool; 44 45 StringPool::Ref ref_a = pool.MakeRef("wut"); 46 StringPool::Ref ref_b = pool.MakeRef("hey"); 47 48 EXPECT_THAT(*ref_a, Eq("wut")); 49 EXPECT_THAT(*ref_b, Eq("hey")); 50 } 51 52 TEST(StringPoolTest, DoNotInsertNewDuplicateString) { 53 StringPool pool; 54 55 StringPool::Ref ref_a = pool.MakeRef("wut"); 56 StringPool::Ref ref_b = pool.MakeRef("wut"); 57 58 EXPECT_THAT(*ref_a, Eq("wut")); 59 EXPECT_THAT(*ref_b, Eq("wut")); 60 EXPECT_THAT(pool.size(), Eq(1u)); 61 } 62 63 TEST(StringPoolTest, MaintainInsertionOrderIndex) { 64 StringPool pool; 65 66 StringPool::Ref ref_a = pool.MakeRef("z"); 67 StringPool::Ref ref_b = pool.MakeRef("a"); 68 StringPool::Ref ref_c = pool.MakeRef("m"); 69 70 EXPECT_THAT(ref_a.index(), Eq(0u)); 71 EXPECT_THAT(ref_b.index(), Eq(1u)); 72 EXPECT_THAT(ref_c.index(), Eq(2u)); 73 } 74 75 TEST(StringPoolTest, PruneStringsWithNoReferences) { 76 StringPool pool; 77 78 StringPool::Ref ref_a = pool.MakeRef("foo"); 79 80 { 81 StringPool::Ref ref_b = pool.MakeRef("wut"); 82 EXPECT_THAT(*ref_b, Eq("wut")); 83 EXPECT_THAT(pool.size(), Eq(2u)); 84 pool.Prune(); 85 EXPECT_THAT(pool.size(), Eq(2u)); 86 } 87 EXPECT_THAT(pool.size(), Eq(2u)); 88 89 { 90 StringPool::Ref ref_c = pool.MakeRef("bar"); 91 EXPECT_THAT(pool.size(), Eq(3u)); 92 93 pool.Prune(); 94 EXPECT_THAT(pool.size(), Eq(2u)); 95 } 96 EXPECT_THAT(pool.size(), Eq(2u)); 97 98 pool.Prune(); 99 EXPECT_THAT(pool.size(), Eq(1u)); 100 } 101 102 TEST(StringPoolTest, SortAndMaintainIndexesInStringReferences) { 103 StringPool pool; 104 105 StringPool::Ref ref_a = pool.MakeRef("z"); 106 StringPool::Ref ref_b = pool.MakeRef("a"); 107 StringPool::Ref ref_c = pool.MakeRef("m"); 108 109 EXPECT_THAT(*ref_a, Eq("z")); 110 EXPECT_THAT(ref_a.index(), Eq(0u)); 111 112 EXPECT_THAT(*ref_b, Eq("a")); 113 EXPECT_THAT(ref_b.index(), Eq(1u)); 114 115 EXPECT_THAT(*ref_c, Eq("m")); 116 EXPECT_THAT(ref_c.index(), Eq(2u)); 117 118 pool.Sort(); 119 120 EXPECT_THAT(*ref_a, Eq("z")); 121 EXPECT_THAT(ref_a.index(), Eq(2u)); 122 123 EXPECT_THAT(*ref_b, Eq("a")); 124 EXPECT_THAT(ref_b.index(), Eq(0u)); 125 126 EXPECT_THAT(*ref_c, Eq("m")); 127 EXPECT_THAT(ref_c.index(), Eq(1u)); 128 } 129 130 TEST(StringPoolTest, SortAndStillDedupe) { 131 StringPool pool; 132 133 StringPool::Ref ref_a = pool.MakeRef("z"); 134 StringPool::Ref ref_b = pool.MakeRef("a"); 135 StringPool::Ref ref_c = pool.MakeRef("m"); 136 137 pool.Sort(); 138 139 StringPool::Ref ref_d = pool.MakeRef("z"); 140 StringPool::Ref ref_e = pool.MakeRef("a"); 141 StringPool::Ref ref_f = pool.MakeRef("m"); 142 143 EXPECT_THAT(ref_d.index(), Eq(ref_a.index())); 144 EXPECT_THAT(ref_e.index(), Eq(ref_b.index())); 145 EXPECT_THAT(ref_f.index(), Eq(ref_c.index())); 146 } 147 148 TEST(StringPoolTest, AddStyles) { 149 StringPool pool; 150 151 StringPool::StyleRef ref = pool.MakeRef(StyleString{{"android"}, {Span{{"b"}, 2, 6}}}); 152 EXPECT_THAT(ref.index(), Eq(0u)); 153 EXPECT_THAT(ref->value, Eq("android")); 154 ASSERT_THAT(ref->spans.size(), Eq(1u)); 155 156 const StringPool::Span& span = ref->spans.front(); 157 EXPECT_THAT(*span.name, Eq("b")); 158 EXPECT_THAT(span.first_char, Eq(2u)); 159 EXPECT_THAT(span.last_char, Eq(6u)); 160 } 161 162 TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) { 163 StringPool pool; 164 165 StringPool::Ref ref = pool.MakeRef("android"); 166 167 StyleString str{{"android"}}; 168 StringPool::StyleRef style_ref = pool.MakeRef(StyleString{{"android"}}); 169 170 EXPECT_THAT(ref.index(), Ne(style_ref.index())); 171 } 172 173 TEST(StringPoolTest, StylesAndStringsAreSeparateAfterSorting) { 174 StringPool pool; 175 176 StringPool::StyleRef ref_a = pool.MakeRef(StyleString{{"beta"}}); 177 StringPool::Ref ref_b = pool.MakeRef("alpha"); 178 StringPool::StyleRef ref_c = pool.MakeRef(StyleString{{"alpha"}}); 179 180 EXPECT_THAT(ref_b.index(), Ne(ref_c.index())); 181 182 pool.Sort(); 183 184 EXPECT_THAT(ref_c.index(), Eq(0u)); 185 EXPECT_THAT(ref_a.index(), Eq(1u)); 186 EXPECT_THAT(ref_b.index(), Eq(2u)); 187 } 188 189 TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) { 190 using namespace android; // For NO_ERROR on Windows. 191 192 StringPool pool; 193 BigBuffer buffer(1024); 194 StringPool::FlattenUtf8(&buffer, pool); 195 196 std::unique_ptr<uint8_t[]> data = util::Copy(buffer); 197 ResStringPool test; 198 ASSERT_THAT(test.setTo(data.get(), buffer.size()), Eq(NO_ERROR)); 199 } 200 201 TEST(StringPoolTest, FlattenOddCharactersUtf16) { 202 using namespace android; // For NO_ERROR on Windows. 203 204 StringPool pool; 205 pool.MakeRef("\u093f"); 206 BigBuffer buffer(1024); 207 StringPool::FlattenUtf16(&buffer, pool); 208 209 std::unique_ptr<uint8_t[]> data = util::Copy(buffer); 210 ResStringPool test; 211 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR); 212 size_t len = 0; 213 const char16_t* str = test.stringAt(0, &len); 214 EXPECT_THAT(len, Eq(1u)); 215 EXPECT_THAT(str, Pointee(Eq(u'\u093f'))); 216 EXPECT_THAT(str[1], Eq(0u)); 217 } 218 219 constexpr const char* sLongString = 220 "" 221 "" 222 "SMS " 223 "" 224 "OFF"; 225 226 TEST(StringPoolTest, Flatten) { 227 using namespace android; // For NO_ERROR on Windows. 228 229 StringPool pool; 230 231 StringPool::Ref ref_a = pool.MakeRef("hello"); 232 StringPool::Ref ref_b = pool.MakeRef("goodbye"); 233 StringPool::Ref ref_c = pool.MakeRef(sLongString); 234 StringPool::Ref ref_d = pool.MakeRef(""); 235 StringPool::StyleRef ref_e = 236 pool.MakeRef(StyleString{{"style"}, {Span{{"b"}, 0, 1}, Span{{"i"}, 2, 3}}}); 237 238 // Styles are always first. 239 EXPECT_THAT(ref_e.index(), Eq(0u)); 240 241 EXPECT_THAT(ref_a.index(), Eq(1u)); 242 EXPECT_THAT(ref_b.index(), Eq(2u)); 243 EXPECT_THAT(ref_c.index(), Eq(3u)); 244 EXPECT_THAT(ref_d.index(), Eq(4u)); 245 246 BigBuffer buffers[2] = {BigBuffer(1024), BigBuffer(1024)}; 247 StringPool::FlattenUtf8(&buffers[0], pool); 248 StringPool::FlattenUtf16(&buffers[1], pool); 249 250 // Test both UTF-8 and UTF-16 buffers. 251 for (const BigBuffer& buffer : buffers) { 252 std::unique_ptr<uint8_t[]> data = util::Copy(buffer); 253 254 ResStringPool test; 255 ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR); 256 257 EXPECT_THAT(util::GetString(test, 1), Eq("hello")); 258 EXPECT_THAT(util::GetString16(test, 1), Eq(u"hello")); 259 260 EXPECT_THAT(util::GetString(test, 2), Eq("goodbye")); 261 EXPECT_THAT(util::GetString16(test, 2), Eq(u"goodbye")); 262 263 EXPECT_THAT(util::GetString(test, 3), Eq(sLongString)); 264 EXPECT_THAT(util::GetString16(test, 3), Eq(util::Utf8ToUtf16(sLongString))); 265 266 size_t len; 267 EXPECT_TRUE(test.stringAt(4, &len) != nullptr || test.string8At(4, &len) != nullptr); 268 269 EXPECT_THAT(util::GetString(test, 0), Eq("style")); 270 EXPECT_THAT(util::GetString16(test, 0), Eq(u"style")); 271 272 const ResStringPool_span* span = test.styleAt(0); 273 ASSERT_THAT(span, NotNull()); 274 EXPECT_THAT(util::GetString(test, span->name.index), Eq("b")); 275 EXPECT_THAT(util::GetString16(test, span->name.index), Eq(u"b")); 276 EXPECT_THAT(span->firstChar, Eq(0u)); 277 EXPECT_THAT(span->lastChar, Eq(1u)); 278 span++; 279 280 ASSERT_THAT(span->name.index, Ne(ResStringPool_span::END)); 281 EXPECT_THAT(util::GetString(test, span->name.index), Eq("i")); 282 EXPECT_THAT(util::GetString16(test, span->name.index), Eq(u"i")); 283 EXPECT_THAT(span->firstChar, Eq(2u)); 284 EXPECT_THAT(span->lastChar, Eq(3u)); 285 span++; 286 287 EXPECT_THAT(span->name.index, Eq(ResStringPool_span::END)); 288 } 289 } 290 291 } // namespace aapt 292