1 /*
2  * Copyright (C) 2016 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 "androidfw/AttributeResolution.h"
18 
19 #include <array>
20 
21 #include "android-base/file.h"
22 #include "android-base/logging.h"
23 #include "android-base/macros.h"
24 
25 #include "TestHelpers.h"
26 #include "data/styles/R.h"
27 
28 using com::android::app::R;
29 
30 namespace android {
31 
32 class AttributeResolutionTest : public ::testing::Test {
33  public:
SetUp()34   virtual void SetUp() override {
35     std::string contents;
36     ASSERT_TRUE(ReadFileFromZipToString(
37         GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
38     ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
39                                    1 /*cookie*/, true /*copyData*/));
40   }
41 
42  protected:
43   ResTable table_;
44 };
45 
46 class AttributeResolutionXmlTest : public AttributeResolutionTest {
47  public:
SetUp()48   virtual void SetUp() override {
49     AttributeResolutionTest::SetUp();
50 
51     std::string contents;
52     ASSERT_TRUE(
53         ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
54                                 "res/layout/layout.xml", &contents));
55 
56     ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
57                                           true /*copyData*/));
58 
59     // Skip to the first tag.
60     while (xml_parser_.next() != ResXMLParser::START_TAG) {
61     }
62   }
63 
64  protected:
65   ResXMLTree xml_parser_;
66 };
67 
TEST_F(AttributeResolutionTest,Theme)68 TEST_F(AttributeResolutionTest, Theme) {
69   ResTable::Theme theme(table_);
70   ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
71 
72   std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
73                                  R::attr::attr_four, R::attr::attr_empty}};
74   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
75 
76   ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
77                            nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(),
78                            attrs.size(), values.data(), nullptr /*out_indices*/));
79 
80   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
81 
82   const uint32_t* values_cursor = values.data();
83   EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
84   EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
85   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
86   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
87   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
88   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
89 
90   values_cursor += STYLE_NUM_ENTRIES;
91   EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]);
92   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
93   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
94   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
95   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
96 
97   values_cursor += STYLE_NUM_ENTRIES;
98   EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
99   EXPECT_EQ(3u, values_cursor[STYLE_DATA]);
100   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
101   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
102   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
103   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
104 
105   values_cursor += STYLE_NUM_ENTRIES;
106   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
107   EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]);
108   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
109   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
110   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
111   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
112 
113   // @empty comes from the theme, so it has the same asset cookie and changing configurations flags
114   // as the theme.
115   values_cursor += STYLE_NUM_ENTRIES;
116   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
117   EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
118   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
119   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
120   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
121   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
122 }
123 
TEST_F(AttributeResolutionXmlTest,XmlParser)124 TEST_F(AttributeResolutionXmlTest, XmlParser) {
125   std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
126                                  R::attr::attr_four, R::attr::attr_empty}};
127   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
128 
129   ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
130                                  nullptr /*out_indices*/));
131 
132   uint32_t* values_cursor = values.data();
133   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
134   EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
135   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
136   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
137   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
138   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
139 
140   values_cursor += STYLE_NUM_ENTRIES;
141   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
142   EXPECT_EQ(0u, values_cursor[STYLE_DATA]);
143   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
144   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
145   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
146   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
147 
148   values_cursor += STYLE_NUM_ENTRIES;
149   EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
150   EXPECT_EQ(10u, values_cursor[STYLE_DATA]);
151   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
152   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
153   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
154   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
155 
156   values_cursor += STYLE_NUM_ENTRIES;
157   EXPECT_EQ(Res_value::TYPE_ATTRIBUTE, values_cursor[STYLE_TYPE]);
158   EXPECT_EQ(R::attr::attr_indirect, values_cursor[STYLE_DATA]);
159   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
160   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
161   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
162   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
163 
164   values_cursor += STYLE_NUM_ENTRIES;
165   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
166   EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]);
167   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
168   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
169   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
170   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
171 }
172 
TEST_F(AttributeResolutionXmlTest,ThemeAndXmlParser)173 TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
174   ResTable::Theme theme(table_);
175   ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
176 
177   std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
178                                  R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
179   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
180   std::array<uint32_t, attrs.size() + 1> indices;
181 
182   ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
183              attrs.size(), values.data(), indices.data());
184 
185   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
186 
187   uint32_t* values_cursor = values.data();
188   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
189   EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
190   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
191   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
192   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
193   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
194 
195   values_cursor += STYLE_NUM_ENTRIES;
196   EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]);
197   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
198   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
199   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
200   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
201 
202   values_cursor += STYLE_NUM_ENTRIES;
203   EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
204   EXPECT_EQ(10u, values_cursor[STYLE_DATA]);
205   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
206   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
207   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
208   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
209 
210   values_cursor += STYLE_NUM_ENTRIES;
211   EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
212   EXPECT_EQ(3u, values_cursor[STYLE_DATA]);
213   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
214   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
215   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
216   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
217 
218   values_cursor += STYLE_NUM_ENTRIES;
219   EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]);
220   EXPECT_EQ(R::string::string_one, values_cursor[STYLE_RESOURCE_ID]);
221   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
222   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
223   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
224 
225   // @empty comes from the theme, so it has the same asset cookie and changing configurations flags
226   // as the theme.
227   values_cursor += STYLE_NUM_ENTRIES;
228   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
229   EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
230   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
231   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
232   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
233   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
234 
235   // The first element of indices contains the number of indices.
236   std::array<uint32_t, 7> expected_indices = {{6u, 0u, 1u, 2u, 3u, 4u, 5u}};
237   EXPECT_EQ(expected_indices, indices);
238 }
239 
240 } // namespace android
241 
242