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 "utils/String16.h"
20 #include "utils/String8.h"
21
22 #include "TestHelpers.h"
23 #include "data/basic/R.h"
24
25 using com::android::basic::R;
26
27 namespace android {
28
makeConfigFrench(ResTable_config * config)29 static void makeConfigFrench(ResTable_config* config) {
30 memset(config, 0, sizeof(*config));
31 config->language[0] = 'f';
32 config->language[1] = 'r';
33 }
34
35 class SplitTest : public ::testing::Test {
36 public:
SetUp()37 void SetUp() override {
38 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
39 "resources.arsc", &basic_contents_));
40 ASSERT_TRUE(
41 ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_de_fr.apk",
42 "resources.arsc", &basic_de_fr_contents_));
43 ASSERT_TRUE(
44 ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_hdpi-v4.apk",
45 "resources.arsc", &basic_hdpi_contents_));
46 ASSERT_TRUE(
47 ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_xhdpi-v4.apk",
48 "resources.arsc", &basic_xhdpi_contents_));
49 ASSERT_TRUE(ReadFileFromZipToString(
50 GetTestDataPath() + "/basic/basic_xxhdpi-v4.apk", "resources.arsc",
51 &basic_xxhdpi_contents_));
52 ASSERT_TRUE(
53 ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk",
54 "resources.arsc", &feature_contents_));
55 }
56
57 protected:
58 std::string basic_contents_;
59 std::string basic_de_fr_contents_;
60 std::string basic_hdpi_contents_;
61 std::string basic_xhdpi_contents_;
62 std::string basic_xxhdpi_contents_;
63 std::string feature_contents_;
64 };
65
TEST_F(SplitTest,TestLoadBase)66 TEST_F(SplitTest, TestLoadBase) {
67 ResTable table;
68 ASSERT_EQ(NO_ERROR,
69 table.add(basic_contents_.data(), basic_contents_.size()));
70 }
71
TEST_F(SplitTest,TestGetResourceFromBase)72 TEST_F(SplitTest, TestGetResourceFromBase) {
73 ResTable_config frenchConfig;
74 makeConfigFrench(&frenchConfig);
75
76 ResTable table;
77 table.setParameters(&frenchConfig);
78
79 ASSERT_EQ(NO_ERROR,
80 table.add(basic_contents_.data(), basic_contents_.size()));
81
82 ResTable_config expectedConfig;
83 memset(&expectedConfig, 0, sizeof(expectedConfig));
84
85 Res_value val;
86 ResTable_config config;
87 ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
88 NULL, &config);
89
90 // The returned block should tell us which string pool to get the value, if it
91 // is a string.
92 EXPECT_GE(block, 0);
93
94 // We expect the default resource to be selected since it is the only resource
95 // configuration.
96 EXPECT_EQ(0, expectedConfig.compare(config));
97
98 EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
99 }
100
TEST_F(SplitTest,TestGetResourceFromSplit)101 TEST_F(SplitTest, TestGetResourceFromSplit) {
102 ResTable_config expectedConfig;
103 makeConfigFrench(&expectedConfig);
104
105 ResTable table;
106 table.setParameters(&expectedConfig);
107
108 ASSERT_EQ(NO_ERROR,
109 table.add(basic_contents_.data(), basic_contents_.size()));
110 ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
111 basic_de_fr_contents_.size()));
112
113 Res_value val;
114 ResTable_config config;
115 ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
116 NULL, &config);
117
118 EXPECT_GE(block, 0);
119
120 EXPECT_EQ(0, expectedConfig.compare(config));
121
122 EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
123 }
124
TEST_F(SplitTest,ResourcesFromBaseAndSplitHaveSameNames)125 TEST_F(SplitTest, ResourcesFromBaseAndSplitHaveSameNames) {
126 ResTable_config expectedConfig;
127 makeConfigFrench(&expectedConfig);
128
129 ResTable table;
130 table.setParameters(&expectedConfig);
131
132 ASSERT_EQ(NO_ERROR,
133 table.add(basic_contents_.data(), basic_contents_.size()));
134
135 ResTable::resource_name baseName;
136 EXPECT_TRUE(table.getResourceName(R::string::test1, false, &baseName));
137
138 ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
139 basic_de_fr_contents_.size()));
140
141 ResTable::resource_name frName;
142 EXPECT_TRUE(table.getResourceName(R::string::test1, false, &frName));
143
144 EXPECT_EQ(String16(baseName.package, baseName.packageLen),
145 String16(frName.package, frName.packageLen));
146
147 EXPECT_EQ(String16(baseName.type, baseName.typeLen),
148 String16(frName.type, frName.typeLen));
149
150 EXPECT_EQ(String16(baseName.name, baseName.nameLen),
151 String16(frName.name, frName.nameLen));
152 }
153
TEST_F(SplitTest,TypeEntrySpecFlagsAreUpdated)154 TEST_F(SplitTest, TypeEntrySpecFlagsAreUpdated) {
155 ResTable_config defaultConfig;
156 memset(&defaultConfig, 0, sizeof(defaultConfig));
157
158 ResTable table;
159 ASSERT_EQ(NO_ERROR,
160 table.add(basic_contents_.data(), basic_contents_.size()));
161
162 Res_value val;
163 uint32_t specFlags = 0;
164 ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
165 &specFlags, NULL);
166 EXPECT_GE(block, 0);
167
168 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), specFlags);
169
170 ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
171 basic_de_fr_contents_.size()));
172
173 uint32_t frSpecFlags = 0;
174 block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
175 &frSpecFlags, NULL);
176 ASSERT_GE(block, 0);
177
178 EXPECT_EQ(static_cast<uint32_t>(ResTable_config::CONFIG_LOCALE | ResTable_typeSpec::SPEC_PUBLIC),
179 frSpecFlags);
180 }
181
TEST_F(SplitTest,SelectBestDensity)182 TEST_F(SplitTest, SelectBestDensity) {
183 ResTable_config baseConfig;
184 memset(&baseConfig, 0, sizeof(baseConfig));
185 baseConfig.density = ResTable_config::DENSITY_XHIGH;
186 baseConfig.sdkVersion = 21;
187
188 ResTable table;
189 table.setParameters(&baseConfig);
190 ASSERT_EQ(NO_ERROR,
191 table.add(basic_contents_.data(), basic_contents_.size()));
192 ASSERT_EQ(NO_ERROR, table.add(basic_hdpi_contents_.data(),
193 basic_hdpi_contents_.size()));
194
195 EXPECT_TRUE(IsStringEqual(table, R::string::density, "hdpi"));
196
197 ASSERT_EQ(NO_ERROR, table.add(basic_xhdpi_contents_.data(),
198 basic_xhdpi_contents_.size()));
199
200 EXPECT_TRUE(IsStringEqual(table, R::string::density, "xhdpi"));
201
202 ASSERT_EQ(NO_ERROR, table.add(basic_xxhdpi_contents_.data(),
203 basic_xxhdpi_contents_.size()));
204
205 EXPECT_TRUE(IsStringEqual(table, R::string::density, "xhdpi"));
206
207 baseConfig.density = ResTable_config::DENSITY_XXHIGH;
208 table.setParameters(&baseConfig);
209
210 EXPECT_TRUE(IsStringEqual(table, R::string::density, "xxhdpi"));
211 }
212
TEST_F(SplitTest,TestNewResourceIsAccessible)213 TEST_F(SplitTest, TestNewResourceIsAccessible) {
214 ResTable table;
215 ASSERT_EQ(NO_ERROR,
216 table.add(basic_contents_.data(), basic_contents_.size()));
217
218 Res_value val;
219 ssize_t block = table.getResource(R::string::test3, &val, MAY_NOT_BE_BAG);
220 EXPECT_LT(block, 0);
221
222 ASSERT_EQ(NO_ERROR,
223 table.add(feature_contents_.data(), feature_contents_.size()));
224
225 block = table.getResource(R::string::test3, &val, MAY_NOT_BE_BAG);
226 ASSERT_GE(block, 0);
227
228 EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
229 }
230
TEST_F(SplitTest,TestNewResourceNameHasCorrectName)231 TEST_F(SplitTest, TestNewResourceNameHasCorrectName) {
232 ResTable table;
233 ASSERT_EQ(NO_ERROR,
234 table.add(basic_contents_.data(), basic_contents_.size()));
235
236 ResTable::resource_name name;
237 EXPECT_FALSE(table.getResourceName(R::string::test3, false, &name));
238
239 ASSERT_EQ(NO_ERROR,
240 table.add(feature_contents_.data(), feature_contents_.size()));
241
242 ASSERT_TRUE(table.getResourceName(R::string::test3, false, &name));
243
244 EXPECT_EQ(String16("com.android.basic"),
245 String16(name.package, name.packageLen));
246
247 EXPECT_EQ(String16("string"), String16(name.type, name.typeLen));
248
249 EXPECT_EQ(String16("test3"), String16(name.name, name.nameLen));
250 }
251
TEST_F(SplitTest,TestNewResourceIsAccessibleByName)252 TEST_F(SplitTest, TestNewResourceIsAccessibleByName) {
253 ResTable table;
254 ASSERT_EQ(NO_ERROR,
255 table.add(basic_contents_.data(), basic_contents_.size()));
256 ASSERT_EQ(NO_ERROR,
257 table.add(feature_contents_.data(), feature_contents_.size()));
258
259 const String16 name("test3");
260 const String16 type("string");
261 const String16 package("com.android.basic");
262 ASSERT_EQ(
263 R::string::test3,
264 table.identifierForName(name.string(), name.size(), type.string(),
265 type.size(), package.string(), package.size()));
266 }
267
268 } // namespace
269