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