Home | History | Annotate | Download | only in aapt2
      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 
     23 namespace aapt {
     24 
     25 TEST(StringPoolTest, InsertOneString) {
     26     StringPool pool;
     27 
     28     StringPool::Ref ref = pool.makeRef(u"wut");
     29     EXPECT_EQ(*ref, u"wut");
     30 }
     31 
     32 TEST(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 
     42 TEST(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 
     53 TEST(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 
     65 TEST(StringPoolTest, PruneStringsWithNoReferences) {
     66     StringPool pool;
     67 
     68     StringPool::Ref refA = pool.makeRef(u"foo");
     69     {
     70         StringPool::Ref ref = pool.makeRef(u"wut");
     71         EXPECT_EQ(*ref, u"wut");
     72         EXPECT_EQ(2u, pool.size());
     73     }
     74     StringPool::Ref refB = pool.makeRef(u"bar");
     75 
     76     EXPECT_EQ(3u, pool.size());
     77     pool.prune();
     78     EXPECT_EQ(2u, pool.size());
     79     StringPool::const_iterator iter = begin(pool);
     80     EXPECT_EQ((*iter)->value, u"foo");
     81     EXPECT_LT((*iter)->index, 2u);
     82     ++iter;
     83     EXPECT_EQ((*iter)->value, u"bar");
     84     EXPECT_LT((*iter)->index, 2u);
     85 }
     86 
     87 TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
     88     StringPool pool;
     89 
     90     StringPool::Ref ref = pool.makeRef(u"z");
     91     StringPool::StyleRef ref2 = pool.makeRef(StyleString{ {u"a"} });
     92     StringPool::Ref ref3 = pool.makeRef(u"m");
     93 
     94     EXPECT_EQ(*ref, u"z");
     95     EXPECT_EQ(0u, ref.getIndex());
     96 
     97     EXPECT_EQ(*(ref2->str), u"a");
     98     EXPECT_EQ(1u, ref2.getIndex());
     99 
    100     EXPECT_EQ(*ref3, u"m");
    101     EXPECT_EQ(2u, ref3.getIndex());
    102 
    103     pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
    104         return a.value < b.value;
    105     });
    106 
    107 
    108     EXPECT_EQ(*ref, u"z");
    109     EXPECT_EQ(2u, ref.getIndex());
    110 
    111     EXPECT_EQ(*(ref2->str), u"a");
    112     EXPECT_EQ(0u, ref2.getIndex());
    113 
    114     EXPECT_EQ(*ref3, u"m");
    115     EXPECT_EQ(1u, ref3.getIndex());
    116 }
    117 
    118 TEST(StringPoolTest, SortAndStillDedupe) {
    119     StringPool pool;
    120 
    121     StringPool::Ref ref = pool.makeRef(u"z");
    122     StringPool::Ref ref2 = pool.makeRef(u"a");
    123     StringPool::Ref ref3 = pool.makeRef(u"m");
    124 
    125     pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
    126         return a.value < b.value;
    127     });
    128 
    129     StringPool::Ref ref4 = pool.makeRef(u"z");
    130     StringPool::Ref ref5 = pool.makeRef(u"a");
    131     StringPool::Ref ref6 = pool.makeRef(u"m");
    132 
    133     EXPECT_EQ(ref4.getIndex(), ref.getIndex());
    134     EXPECT_EQ(ref5.getIndex(), ref2.getIndex());
    135     EXPECT_EQ(ref6.getIndex(), ref3.getIndex());
    136 }
    137 
    138 TEST(StringPoolTest, AddStyles) {
    139     StringPool pool;
    140 
    141     StyleString str {
    142         { u"android" },
    143         {
    144             Span{ { u"b" }, 2, 6 }
    145         }
    146     };
    147 
    148     StringPool::StyleRef ref = pool.makeRef(str);
    149 
    150     EXPECT_EQ(0u, ref.getIndex());
    151     EXPECT_EQ(std::u16string(u"android"), *(ref->str));
    152     ASSERT_EQ(1u, ref->spans.size());
    153 
    154     const StringPool::Span& span = ref->spans.front();
    155     EXPECT_EQ(*(span.name), u"b");
    156     EXPECT_EQ(2u, span.firstChar);
    157     EXPECT_EQ(6u, span.lastChar);
    158 }
    159 
    160 TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
    161     StringPool pool;
    162 
    163     StringPool::Ref ref = pool.makeRef(u"android");
    164 
    165     StyleString str { { u"android" } };
    166     StringPool::StyleRef styleRef = pool.makeRef(str);
    167 
    168     EXPECT_NE(ref.getIndex(), styleRef.getIndex());
    169 }
    170 
    171 TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
    172     using namespace android; // For NO_ERROR on Windows.
    173 
    174     StringPool pool;
    175     BigBuffer buffer(1024);
    176     StringPool::flattenUtf8(&buffer, pool);
    177 
    178     std::unique_ptr<uint8_t[]> data = util::copy(buffer);
    179     ResStringPool test;
    180     ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
    181 }
    182 
    183 TEST(StringPoolTest, FlattenOddCharactersUtf16) {
    184     using namespace android; // For NO_ERROR on Windows.
    185 
    186     StringPool pool;
    187     pool.makeRef(u"\u093f");
    188     BigBuffer buffer(1024);
    189     StringPool::flattenUtf16(&buffer, pool);
    190 
    191     std::unique_ptr<uint8_t[]> data = util::copy(buffer);
    192     ResStringPool test;
    193     ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
    194     size_t len = 0;
    195     const char16_t* str = test.stringAt(0, &len);
    196     EXPECT_EQ(1u, len);
    197     EXPECT_EQ(u'\u093f', *str);
    198     EXPECT_EQ(0u, str[1]);
    199 }
    200 
    201 constexpr const char16_t* sLongString = u"SMS OFF";
    202 
    203 TEST(StringPoolTest, FlattenUtf8) {
    204     using namespace android; // For NO_ERROR on Windows.
    205 
    206     StringPool pool;
    207 
    208     StringPool::Ref ref1 = pool.makeRef(u"hello");
    209     StringPool::Ref ref2 = pool.makeRef(u"goodbye");
    210     StringPool::Ref ref3 = pool.makeRef(sLongString);
    211     StringPool::StyleRef ref4 = pool.makeRef(StyleString{
    212             { u"style" },
    213             { Span{ { u"b" }, 0, 1 }, Span{ { u"i" }, 2, 3 } }
    214     });
    215 
    216     EXPECT_EQ(0u, ref1.getIndex());
    217     EXPECT_EQ(1u, ref2.getIndex());
    218     EXPECT_EQ(2u, ref3.getIndex());
    219     EXPECT_EQ(3u, ref4.getIndex());
    220 
    221     BigBuffer buffer(1024);
    222     StringPool::flattenUtf8(&buffer, pool);
    223 
    224     std::unique_ptr<uint8_t[]> data = util::copy(buffer);
    225     {
    226         ResStringPool test;
    227         ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
    228 
    229         EXPECT_EQ(util::getString(test, 0), u"hello");
    230         EXPECT_EQ(util::getString(test, 1), u"goodbye");
    231         EXPECT_EQ(util::getString(test, 2), sLongString);
    232         EXPECT_EQ(util::getString(test, 3), u"style");
    233 
    234         const ResStringPool_span* span = test.styleAt(3);
    235         ASSERT_NE(nullptr, span);
    236         EXPECT_EQ(util::getString(test, span->name.index), u"b");
    237         EXPECT_EQ(0u, span->firstChar);
    238         EXPECT_EQ(1u, span->lastChar);
    239         span++;
    240 
    241         ASSERT_NE(ResStringPool_span::END, span->name.index);
    242         EXPECT_EQ(util::getString(test, span->name.index), u"i");
    243         EXPECT_EQ(2u, span->firstChar);
    244         EXPECT_EQ(3u, span->lastChar);
    245         span++;
    246 
    247         EXPECT_EQ(ResStringPool_span::END, span->name.index);
    248     }
    249 }
    250 
    251 } // namespace aapt
    252