• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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/ResourceTypes.h>
18 
19 #include <codecvt>
20 #include <locale>
21 #include <string>
22 
23 #include <utils/String8.h>
24 #include <utils/String16.h>
25 #include "TestHelpers.h"
26 #include "data/basic/R.h"
27 #include "data/lib/R.h"
28 
29 #include <gtest/gtest.h>
30 
31 using namespace android;
32 
33 namespace {
34 
35 /**
36  * Include a binary resource table.
37  *
38  * Package: com.android.test.basic
39  */
40 #include "data/basic/basic_arsc.h"
41 
42 #include "data/lib/lib_arsc.h"
43 
TEST(ResTableTest,shouldLoadSuccessfully)44 TEST(ResTableTest, shouldLoadSuccessfully) {
45     ResTable table;
46     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
47 }
48 
TEST(ResTableTest,simpleTypeIsRetrievedCorrectly)49 TEST(ResTableTest, simpleTypeIsRetrievedCorrectly) {
50     ResTable table;
51     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
52 
53     EXPECT_TRUE(IsStringEqual(table, base::R::string::test1, "test1"));
54 }
55 
TEST(ResTableTest,resourceNameIsResolved)56 TEST(ResTableTest, resourceNameIsResolved) {
57     ResTable table;
58     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
59 
60     String16 defPackage("com.android.test.basic");
61     String16 testName("@string/test1");
62     uint32_t resID = table.identifierForName(testName.string(), testName.size(),
63                                              0, 0,
64                                              defPackage.string(), defPackage.size());
65     ASSERT_NE(uint32_t(0x00000000), resID);
66     ASSERT_EQ(base::R::string::test1, resID);
67 }
68 
TEST(ResTableTest,noParentThemeIsAppliedCorrectly)69 TEST(ResTableTest, noParentThemeIsAppliedCorrectly) {
70     ResTable table;
71     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
72 
73     ResTable::Theme theme(table);
74     ASSERT_EQ(NO_ERROR, theme.applyStyle(base::R::style::Theme1));
75 
76     Res_value val;
77     uint32_t specFlags = 0;
78     ssize_t index = theme.getAttribute(base::R::attr::attr1, &val, &specFlags);
79     ASSERT_GE(index, 0);
80     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
81     ASSERT_EQ(uint32_t(100), val.data);
82 
83     index = theme.getAttribute(base::R::attr::attr2, &val, &specFlags);
84     ASSERT_GE(index, 0);
85     ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
86     ASSERT_EQ(base::R::integer::number1, val.data);
87 }
88 
TEST(ResTableTest,parentThemeIsAppliedCorrectly)89 TEST(ResTableTest, parentThemeIsAppliedCorrectly) {
90     ResTable table;
91     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
92 
93     ResTable::Theme theme(table);
94     ASSERT_EQ(NO_ERROR, theme.applyStyle(base::R::style::Theme2));
95 
96     Res_value val;
97     uint32_t specFlags = 0;
98     ssize_t index = theme.getAttribute(base::R::attr::attr1, &val, &specFlags);
99     ASSERT_GE(index, 0);
100     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
101     ASSERT_EQ(uint32_t(300), val.data);
102 
103     index = theme.getAttribute(base::R::attr::attr2, &val, &specFlags);
104     ASSERT_GE(index, 0);
105     ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
106     ASSERT_EQ(base::R::integer::number1, val.data);
107 }
108 
TEST(ResTableTest,libraryThemeIsAppliedCorrectly)109 TEST(ResTableTest, libraryThemeIsAppliedCorrectly) {
110     ResTable table;
111     ASSERT_EQ(NO_ERROR, table.add(lib_arsc, lib_arsc_len));
112 
113     ResTable::Theme theme(table);
114     ASSERT_EQ(NO_ERROR, theme.applyStyle(lib::R::style::Theme));
115 
116     Res_value val;
117     uint32_t specFlags = 0;
118     ssize_t index = theme.getAttribute(lib::R::attr::attr1, &val, &specFlags);
119     ASSERT_GE(index, 0);
120     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
121     ASSERT_EQ(uint32_t(700), val.data);
122 }
123 
TEST(ResTableTest,referenceToBagIsNotResolved)124 TEST(ResTableTest, referenceToBagIsNotResolved) {
125     ResTable table;
126     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
127 
128     Res_value val;
129     ssize_t block = table.getResource(base::R::integer::number2, &val, MAY_NOT_BE_BAG);
130     ASSERT_GE(block, 0);
131     ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
132     ASSERT_EQ(base::R::array::integerArray1, val.data);
133 
134     ssize_t newBlock = table.resolveReference(&val, block);
135     EXPECT_EQ(block, newBlock);
136     EXPECT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
137     EXPECT_EQ(base::R::array::integerArray1, val.data);
138 }
139 
TEST(ResTableTest,resourcesStillAccessibleAfterParameterChange)140 TEST(ResTableTest, resourcesStillAccessibleAfterParameterChange) {
141     ResTable table;
142     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
143 
144     Res_value val;
145     ssize_t block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
146     ASSERT_GE(block, 0);
147     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
148 
149     const ResTable::bag_entry* entry;
150     ssize_t count = table.lockBag(base::R::array::integerArray1, &entry);
151     ASSERT_GE(count, 0);
152     table.unlockBag(entry);
153 
154     ResTable_config param;
155     memset(&param, 0, sizeof(param));
156     param.density = 320;
157     table.setParameters(&param);
158 
159     block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
160     ASSERT_GE(block, 0);
161     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
162 
163     count = table.lockBag(base::R::array::integerArray1, &entry);
164     ASSERT_GE(count, 0);
165     table.unlockBag(entry);
166 }
167 
TEST(ResTableTest,resourceIsOverridenWithBetterConfig)168 TEST(ResTableTest, resourceIsOverridenWithBetterConfig) {
169     ResTable table;
170     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
171 
172     Res_value val;
173     ssize_t block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
174     ASSERT_GE(block, 0);
175     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
176     ASSERT_EQ(uint32_t(200), val.data);
177 
178     ResTable_config param;
179     memset(&param, 0, sizeof(param));
180     param.language[0] = 's';
181     param.language[1] = 'v';
182     param.country[0] = 'S';
183     param.country[1] = 'E';
184     table.setParameters(&param);
185 
186     block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
187     ASSERT_GE(block, 0);
188     ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
189     ASSERT_EQ(uint32_t(400), val.data);
190 }
191 
TEST(ResTableTest,emptyTableHasSensibleDefaults)192 TEST(ResTableTest, emptyTableHasSensibleDefaults) {
193     const int32_t assetCookie = 1;
194 
195     ResTable table;
196     ASSERT_EQ(NO_ERROR, table.addEmpty(assetCookie));
197 
198     // Adding an empty table gives us one table!
199     ASSERT_EQ(uint32_t(1), table.getTableCount());
200 
201     // Adding an empty table doesn't mean we get packages.
202     ASSERT_EQ(uint32_t(0), table.getBasePackageCount());
203 
204     Res_value val;
205     ASSERT_LT(table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG), 0);
206 }
207 
testU16StringToInt(const char16_t * str,uint32_t expectedValue,bool expectSuccess,bool expectHex)208 void testU16StringToInt(const char16_t* str, uint32_t expectedValue,
209                         bool expectSuccess, bool expectHex) {
210     size_t len = std::char_traits<char16_t>::length(str);
211 
212     // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :(
213     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
214     std::string s = convert.to_bytes(std::u16string(str, len));
215 
216     Res_value out = {};
217     ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out))
218         << "Failed with " << s;
219 
220     if (!expectSuccess) {
221         ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s;
222         return;
223     }
224 
225     if (expectHex) {
226         ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s;
227     } else {
228         ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s;
229     }
230 
231     ASSERT_EQ(expectedValue, out.data) << "Failed with " << s;
232 }
233 
TEST(ResTableTest,U16StringToInt)234 TEST(ResTableTest, U16StringToInt) {
235     testU16StringToInt(u"", 0U, false, false);
236     testU16StringToInt(u"    ", 0U, false, false);
237     testU16StringToInt(u"\t\n", 0U, false, false);
238 
239     testU16StringToInt(u"abcd", 0U, false, false);
240     testU16StringToInt(u"10abcd", 0U, false, false);
241     testU16StringToInt(u"42 42", 0U, false, false);
242     testU16StringToInt(u"- 42", 0U, false, false);
243     testU16StringToInt(u"-", 0U, false, false);
244 
245     testU16StringToInt(u"0x", 0U, false, true);
246     testU16StringToInt(u"0xnope", 0U, false, true);
247     testU16StringToInt(u"0X42", 0U, false, true);
248     testU16StringToInt(u"0x42 0x42", 0U, false, true);
249     testU16StringToInt(u"-0x0", 0U, false, true);
250     testU16StringToInt(u"-0x42", 0U, false, true);
251     testU16StringToInt(u"- 0x42", 0U, false, true);
252 
253     // Note that u" 42" would pass. This preserves the old behavior, but it may
254     // not be desired.
255     testU16StringToInt(u"42 ", 0U, false, false);
256     testU16StringToInt(u"0x42 ", 0U, false, true);
257 
258     // Decimal cases.
259     testU16StringToInt(u"0", 0U, true, false);
260     testU16StringToInt(u"-0", 0U, true, false);
261     testU16StringToInt(u"42", 42U, true, false);
262     testU16StringToInt(u" 42", 42U, true, false);
263     testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false);
264     testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false);
265     testU16StringToInt(u"042", 42U, true, false);
266     testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false);
267 
268     // Hex cases.
269     testU16StringToInt(u"0x0", 0x0, true, true);
270     testU16StringToInt(u"0x42", 0x42, true, true);
271     testU16StringToInt(u" 0x42", 0x42, true, true);
272 
273     // Just before overflow cases:
274     testU16StringToInt(u"2147483647", INT_MAX, true, false);
275     testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true,
276                        false);
277     testU16StringToInt(u"0xffffffff", UINT_MAX, true, true);
278 
279     // Overflow cases:
280     testU16StringToInt(u"2147483648", 0U, false, false);
281     testU16StringToInt(u"-2147483649", 0U, false, false);
282     testU16StringToInt(u"0x1ffffffff", 0U, false, true);
283 }
284 
285 }
286