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 "ResourceUtils.h"
     18 
     19 #include "SdkConstants.h"
     20 #include "Resource.h"
     21 #include "test/Test.h"
     22 
     23 using ::aapt::test::ValueEq;
     24 using ::android::Res_value;
     25 using ::android::ResTable_map;
     26 using ::testing::Eq;
     27 using ::testing::NotNull;
     28 using ::testing::Pointee;
     29 
     30 namespace aapt {
     31 
     32 TEST(ResourceUtilsTest, ParseBool) {
     33   EXPECT_THAT(ResourceUtils::ParseBool("true"), Eq(Maybe<bool>(true)));
     34   EXPECT_THAT(ResourceUtils::ParseBool("TRUE"), Eq(Maybe<bool>(true)));
     35   EXPECT_THAT(ResourceUtils::ParseBool("True"), Eq(Maybe<bool>(true)));
     36 
     37   EXPECT_THAT(ResourceUtils::ParseBool("false"), Eq(Maybe<bool>(false)));
     38   EXPECT_THAT(ResourceUtils::ParseBool("FALSE"), Eq(Maybe<bool>(false)));
     39   EXPECT_THAT(ResourceUtils::ParseBool("False"), Eq(Maybe<bool>(false)));
     40 
     41   EXPECT_THAT(ResourceUtils::ParseBool(" False\n "), Eq(Maybe<bool>(false)));
     42 }
     43 
     44 TEST(ResourceUtilsTest, ParseResourceName) {
     45   ResourceNameRef actual;
     46   bool actual_priv = false;
     47   EXPECT_TRUE(ResourceUtils::ParseResourceName("android:color/foo", &actual, &actual_priv));
     48   EXPECT_THAT(actual, Eq(ResourceNameRef("android", ResourceType::kColor, "foo")));
     49   EXPECT_FALSE(actual_priv);
     50 
     51   EXPECT_TRUE(ResourceUtils::ParseResourceName("color/foo", &actual, &actual_priv));
     52   EXPECT_THAT(actual, Eq(ResourceNameRef({}, ResourceType::kColor, "foo")));
     53   EXPECT_FALSE(actual_priv);
     54 
     55   EXPECT_TRUE(ResourceUtils::ParseResourceName("*android:color/foo", &actual, &actual_priv));
     56   EXPECT_THAT(actual, Eq(ResourceNameRef("android", ResourceType::kColor, "foo")));
     57   EXPECT_TRUE(actual_priv);
     58 
     59   EXPECT_FALSE(ResourceUtils::ParseResourceName(android::StringPiece(), &actual, &actual_priv));
     60 }
     61 
     62 TEST(ResourceUtilsTest, ParseReferenceWithNoPackage) {
     63   ResourceNameRef actual;
     64   bool create = false;
     65   bool private_ref = false;
     66   EXPECT_TRUE(ResourceUtils::ParseReference("@color/foo", &actual, &create, &private_ref));
     67   EXPECT_THAT(actual, Eq(ResourceNameRef({}, ResourceType::kColor, "foo")));
     68   EXPECT_FALSE(create);
     69   EXPECT_FALSE(private_ref);
     70 }
     71 
     72 TEST(ResourceUtilsTest, ParseReferenceWithPackage) {
     73   ResourceNameRef actual;
     74   bool create = false;
     75   bool private_ref = false;
     76   EXPECT_TRUE(ResourceUtils::ParseReference("@android:color/foo", &actual, &create, &private_ref));
     77   EXPECT_THAT(actual, Eq(ResourceNameRef("android", ResourceType::kColor, "foo")));
     78   EXPECT_FALSE(create);
     79   EXPECT_FALSE(private_ref);
     80 }
     81 
     82 TEST(ResourceUtilsTest, ParseReferenceWithSurroundingWhitespace) {
     83   ResourceNameRef actual;
     84   bool create = false;
     85   bool private_ref = false;
     86   EXPECT_TRUE(ResourceUtils::ParseReference("\t @android:color/foo\n \n\t", &actual, &create, &private_ref));
     87   EXPECT_THAT(actual, Eq(ResourceNameRef("android", ResourceType::kColor, "foo")));
     88   EXPECT_FALSE(create);
     89   EXPECT_FALSE(private_ref);
     90 }
     91 
     92 TEST(ResourceUtilsTest, ParseAutoCreateIdReference) {
     93   ResourceNameRef actual;
     94   bool create = false;
     95   bool private_ref = false;
     96   EXPECT_TRUE(ResourceUtils::ParseReference("@+android:id/foo", &actual, &create, &private_ref));
     97   EXPECT_THAT(actual, Eq(ResourceNameRef("android", ResourceType::kId, "foo")));
     98   EXPECT_TRUE(create);
     99   EXPECT_FALSE(private_ref);
    100 }
    101 
    102 TEST(ResourceUtilsTest, ParsePrivateReference) {
    103   ResourceNameRef actual;
    104   bool create = false;
    105   bool private_ref = false;
    106   EXPECT_TRUE(ResourceUtils::ParseReference("@*android:id/foo", &actual, &create, &private_ref));
    107   EXPECT_THAT(actual, Eq(ResourceNameRef("android", ResourceType::kId, "foo")));
    108   EXPECT_FALSE(create);
    109   EXPECT_TRUE(private_ref);
    110 }
    111 
    112 TEST(ResourceUtilsTest, FailToParseAutoCreateNonIdReference) {
    113   bool create = false;
    114   bool private_ref = false;
    115   ResourceNameRef actual;
    116   EXPECT_FALSE(ResourceUtils::ParseReference("@+android:color/foo", &actual, &create, &private_ref));
    117 }
    118 
    119 TEST(ResourceUtilsTest, ParseAttributeReferences) {
    120   EXPECT_TRUE(ResourceUtils::IsAttributeReference("?android"));
    121   EXPECT_TRUE(ResourceUtils::IsAttributeReference("?android:foo"));
    122   EXPECT_TRUE(ResourceUtils::IsAttributeReference("?attr/foo"));
    123   EXPECT_TRUE(ResourceUtils::IsAttributeReference("?android:attr/foo"));
    124 }
    125 
    126 TEST(ResourceUtilsTest, FailParseIncompleteReference) {
    127   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?style/foo"));
    128   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?android:style/foo"));
    129   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?android:"));
    130   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?android:attr/"));
    131   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?:attr/"));
    132   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?:attr/foo"));
    133   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?:/"));
    134   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?:/foo"));
    135   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?attr/"));
    136   EXPECT_FALSE(ResourceUtils::IsAttributeReference("?/foo"));
    137 }
    138 
    139 TEST(ResourceUtilsTest, ParseStyleParentReference) {
    140   const ResourceName kAndroidStyleFooName("android", ResourceType::kStyle, "foo");
    141   const ResourceName kStyleFooName({}, ResourceType::kStyle, "foo");
    142 
    143   std::string err_str;
    144   Maybe<Reference> ref = ResourceUtils::ParseStyleParentReference("@android:style/foo", &err_str);
    145   ASSERT_TRUE(ref);
    146   EXPECT_THAT(ref.value().name, Eq(make_value(kAndroidStyleFooName)));
    147 
    148   ref = ResourceUtils::ParseStyleParentReference("@style/foo", &err_str);
    149   ASSERT_TRUE(ref);
    150   EXPECT_THAT(ref.value().name, Eq(make_value(kStyleFooName)));
    151 
    152   ref = ResourceUtils::ParseStyleParentReference("?android:style/foo", &err_str);
    153   ASSERT_TRUE(ref);
    154   EXPECT_THAT(ref.value().name, Eq(make_value(kAndroidStyleFooName)));
    155 
    156   ref = ResourceUtils::ParseStyleParentReference("?style/foo", &err_str);
    157   ASSERT_TRUE(ref);
    158   EXPECT_THAT(ref.value().name, Eq(make_value(kStyleFooName)));
    159 
    160   ref = ResourceUtils::ParseStyleParentReference("android:style/foo", &err_str);
    161   ASSERT_TRUE(ref);
    162   EXPECT_THAT(ref.value().name, Eq(make_value(kAndroidStyleFooName)));
    163 
    164   ref = ResourceUtils::ParseStyleParentReference("android:foo", &err_str);
    165   ASSERT_TRUE(ref);
    166   EXPECT_THAT(ref.value().name, Eq(make_value(kAndroidStyleFooName)));
    167 
    168   ref = ResourceUtils::ParseStyleParentReference("@android:foo", &err_str);
    169   ASSERT_TRUE(ref);
    170   EXPECT_THAT(ref.value().name, Eq(make_value(kAndroidStyleFooName)));
    171 
    172   ref = ResourceUtils::ParseStyleParentReference("foo", &err_str);
    173   ASSERT_TRUE(ref);
    174   EXPECT_THAT(ref.value().name, Eq(make_value(kStyleFooName)));
    175 
    176   ref = ResourceUtils::ParseStyleParentReference("*android:style/foo", &err_str);
    177   ASSERT_TRUE(ref);
    178   EXPECT_THAT(ref.value().name, Eq(make_value(kAndroidStyleFooName)));
    179   EXPECT_TRUE(ref.value().private_reference);
    180 }
    181 
    182 TEST(ResourceUtilsTest, ParseEmptyFlag) {
    183   std::unique_ptr<Attribute> attr = test::AttributeBuilder()
    184                                         .SetTypeMask(ResTable_map::TYPE_FLAGS)
    185                                         .AddItem("one", 0x01)
    186                                         .AddItem("two", 0x02)
    187                                         .Build();
    188 
    189   std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseFlagSymbol(attr.get(), "");
    190   ASSERT_THAT(result, NotNull());
    191   EXPECT_THAT(result->value.data, Eq(0u));
    192 }
    193 
    194 TEST(ResourceUtilsTest, NullIsEmptyReference) {
    195   ASSERT_THAT(ResourceUtils::MakeNull(), Pointee(ValueEq(Reference())));
    196   ASSERT_THAT(ResourceUtils::TryParseNullOrEmpty("@null"), Pointee(ValueEq(Reference())));
    197 }
    198 
    199 TEST(ResourceUtilsTest, EmptyIsBinaryPrimitive) {
    200   ASSERT_THAT(ResourceUtils::MakeEmpty(), Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_NULL, Res_value::DATA_NULL_EMPTY))));
    201   ASSERT_THAT(ResourceUtils::TryParseNullOrEmpty("@empty"), Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_NULL, Res_value::DATA_NULL_EMPTY))));
    202 }
    203 
    204 TEST(ResourceUtilsTest, ItemsWithWhitespaceAreParsedCorrectly) {
    205   EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" 12\n   ", ResTable_map::TYPE_INTEGER),
    206               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_INT_DEC, 12u))));
    207   EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" true\n   ", ResTable_map::TYPE_BOOLEAN),
    208               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_INT_BOOLEAN, 0xffffffffu))));
    209 
    210   const float expected_float = 12.0f;
    211   const uint32_t expected_float_flattened = *(uint32_t*)&expected_float;
    212   EXPECT_THAT(ResourceUtils::TryParseItemForAttribute(" 12.0\n   ", ResTable_map::TYPE_FLOAT),
    213               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened))));
    214 }
    215 
    216 TEST(ResourceUtilsTest, ParseSdkVersionWithCodename) {
    217   const android::StringPiece codename =
    218       GetDevelopmentSdkCodeNameAndVersion().first;
    219   const int version = GetDevelopmentSdkCodeNameAndVersion().second;
    220 
    221   EXPECT_THAT(ResourceUtils::ParseSdkVersion(codename), Eq(Maybe<int>(version)));
    222   EXPECT_THAT(
    223       ResourceUtils::ParseSdkVersion(codename.to_string() + ".fingerprint"),
    224       Eq(Maybe<int>(version)));
    225 }
    226 
    227 TEST(ResourceUtilsTest, StringBuilderWhitespaceRemoval) {
    228   EXPECT_THAT(ResourceUtils::StringBuilder()
    229                   .AppendText("    hey guys ")
    230                   .AppendText(" this is so cool ")
    231                   .to_string(),
    232               Eq(" hey guys this is so cool "));
    233   EXPECT_THAT(ResourceUtils::StringBuilder()
    234                   .AppendText(" \" wow,  so many \t ")
    235                   .AppendText("spaces. \"what? ")
    236                   .to_string(),
    237               Eq("  wow,  so many \t spaces. what? "));
    238   EXPECT_THAT(ResourceUtils::StringBuilder()
    239                   .AppendText("  where \t ")
    240                   .AppendText(" \nis the pie?")
    241                   .to_string(),
    242               Eq(" where is the pie?"));
    243 }
    244 
    245 TEST(ResourceUtilsTest, StringBuilderEscaping) {
    246   EXPECT_THAT(ResourceUtils::StringBuilder()
    247                   .AppendText("hey guys\\n ")
    248                   .AppendText(" this \\t is so\\\\ cool")
    249                   .to_string(),
    250               Eq("hey guys\n this \t is so\\ cool"));
    251   EXPECT_THAT(ResourceUtils::StringBuilder().AppendText("\\@\\?\\#\\\\\\'").to_string(),
    252               Eq("@?#\\\'"));
    253 }
    254 
    255 TEST(ResourceUtilsTest, StringBuilderMisplacedQuote) {
    256   ResourceUtils::StringBuilder builder;
    257   EXPECT_FALSE(builder.AppendText("they're coming!"));
    258 }
    259 
    260 TEST(ResourceUtilsTest, StringBuilderUnicodeCodes) {
    261   EXPECT_THAT(ResourceUtils::StringBuilder().AppendText("\\u00AF\\u0AF0 woah").to_string(),
    262               Eq("\u00AF\u0AF0 woah"));
    263   EXPECT_FALSE(ResourceUtils::StringBuilder().AppendText("\\u00 yo"));
    264 }
    265 
    266 TEST(ResourceUtilsTest, StringBuilderPreserveSpaces) {
    267   EXPECT_THAT(ResourceUtils::StringBuilder(true /*preserve_spaces*/).AppendText("\"").to_string(),
    268               Eq("\""));
    269 }
    270 
    271 }  // namespace aapt
    272