blob: dfff9c00922c4849ff4f8ecbedfd3fcb3b43f2ab [file] [log] [blame]
Adam Lesinski9d9cc622014-08-29 14:10:04 -07001/*
Adam Lesinski7ad11102016-10-28 16:39:15 -07002 * Copyright (C) 2016 The Android Open Source Project
Adam Lesinski9d9cc622014-08-29 14:10:04 -07003 *
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
Adam Lesinski7ad11102016-10-28 16:39:15 -070017#include "androidfw/AssetManager2.h"
Adam Lesinski9d9cc622014-08-29 14:10:04 -070018
Adam Lesinski7ad11102016-10-28 16:39:15 -070019#include "android-base/logging.h"
Adam Lesinski4c67a472016-11-10 16:43:59 -080020
Adam Lesinski9d9cc622014-08-29 14:10:04 -070021#include "TestHelpers.h"
Adam Lesinski929d6512017-01-16 19:11:19 -080022#include "androidfw/ResourceUtils.h"
Adam Lesinskida431a22016-12-29 16:08:16 -050023#include "data/lib_one/R.h"
24#include "data/libclient/R.h"
Adam Lesinski7ad11102016-10-28 16:39:15 -070025#include "data/styles/R.h"
Adam Lesinski9d9cc622014-08-29 14:10:04 -070026
Adam Lesinski4c67a472016-11-10 16:43:59 -080027namespace app = com::android::app;
Adam Lesinskida431a22016-12-29 16:08:16 -050028namespace lib_one = com::android::lib_one;
29namespace libclient = com::android::libclient;
Adam Lesinski9d9cc622014-08-29 14:10:04 -070030
Adam Lesinski4c67a472016-11-10 16:43:59 -080031namespace android {
Adam Lesinski9d9cc622014-08-29 14:10:04 -070032
Adam Lesinski7ad11102016-10-28 16:39:15 -070033class ThemeTest : public ::testing::Test {
34 public:
35 void SetUp() override {
36 style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
37 ASSERT_NE(nullptr, style_assets_);
Adam Lesinskida431a22016-12-29 16:08:16 -050038
39 libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
40 ASSERT_NE(nullptr, libclient_assets_);
41
42 lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
43 ASSERT_NE(nullptr, lib_one_assets_);
44
45 lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
46 ASSERT_NE(nullptr, lib_two_assets_);
Adam Lesinski7ad11102016-10-28 16:39:15 -070047 }
Adam Lesinski9d9cc622014-08-29 14:10:04 -070048
Adam Lesinski7ad11102016-10-28 16:39:15 -070049 protected:
Adam Lesinski0c405242017-01-13 20:47:26 -080050 std::unique_ptr<const ApkAssets> style_assets_;
51 std::unique_ptr<const ApkAssets> libclient_assets_;
52 std::unique_ptr<const ApkAssets> lib_one_assets_;
53 std::unique_ptr<const ApkAssets> lib_two_assets_;
Adam Lesinski7ad11102016-10-28 16:39:15 -070054};
Adam Lesinski9d9cc622014-08-29 14:10:04 -070055
Adam Lesinski7ad11102016-10-28 16:39:15 -070056TEST_F(ThemeTest, EmptyTheme) {
57 AssetManager2 assetmanager;
58 assetmanager.SetApkAssets({style_assets_.get()});
Adam Lesinski9d9cc622014-08-29 14:10:04 -070059
Adam Lesinski7ad11102016-10-28 16:39:15 -070060 std::unique_ptr<Theme> theme = assetmanager.NewTheme();
61 EXPECT_EQ(0u, theme->GetChangingConfigurations());
62 EXPECT_EQ(&assetmanager, theme->GetAssetManager());
Adam Lesinski4c67a472016-11-10 16:43:59 -080063
Adam Lesinski7ad11102016-10-28 16:39:15 -070064 Res_value value;
65 uint32_t flags;
66 EXPECT_EQ(kInvalidCookie, theme->GetAttribute(app::R::attr::attr_one, &value, &flags));
67}
Adam Lesinski4c67a472016-11-10 16:43:59 -080068
Adam Lesinski7ad11102016-10-28 16:39:15 -070069TEST_F(ThemeTest, SingleThemeNoParent) {
70 AssetManager2 assetmanager;
71 assetmanager.SetApkAssets({style_assets_.get()});
72
73 std::unique_ptr<Theme> theme = assetmanager.NewTheme();
74 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleOne));
75
76 Res_value value;
77 uint32_t flags;
78 ApkAssetsCookie cookie;
79
80 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
81 ASSERT_NE(kInvalidCookie, cookie);
82 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
83 EXPECT_EQ(1u, value.data);
84 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
85
86 cookie = theme->GetAttribute(app::R::attr::attr_two, &value, &flags);
87 ASSERT_NE(kInvalidCookie, cookie);
88 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
89 EXPECT_EQ(2u, value.data);
90 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
91}
92
93TEST_F(ThemeTest, SingleThemeWithParent) {
94 AssetManager2 assetmanager;
95 assetmanager.SetApkAssets({style_assets_.get()});
96
97 std::unique_ptr<Theme> theme = assetmanager.NewTheme();
98 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
99
100 Res_value value;
101 uint32_t flags;
102 ApkAssetsCookie cookie;
103
104 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
105 ASSERT_NE(kInvalidCookie, cookie);
106 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
107 EXPECT_EQ(1u, value.data);
108 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
109
110 cookie = theme->GetAttribute(app::R::attr::attr_two, &value, &flags);
111 ASSERT_NE(kInvalidCookie, cookie);
112 EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
113 EXPECT_EQ(0, cookie);
114 EXPECT_EQ(std::string("string"),
115 GetStringFromPool(assetmanager.GetStringPoolForCookie(0), value.data));
116 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
117
118 // This attribute should point to an attr_indirect, so the result should be 3.
119 cookie = theme->GetAttribute(app::R::attr::attr_three, &value, &flags);
120 ASSERT_NE(kInvalidCookie, cookie);
121 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
122 EXPECT_EQ(3u, value.data);
123 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
124}
125
126TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) {
127 AssetManager2 assetmanager;
128 assetmanager.SetApkAssets({style_assets_.get()});
129
130 std::unique_ptr<Theme> theme = assetmanager.NewTheme();
131 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
132 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleThree));
133
134 Res_value value;
135 uint32_t flags;
136 ApkAssetsCookie cookie;
137
138 // attr_one is still here from the base.
139 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
140 ASSERT_NE(kInvalidCookie, cookie);
141 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
142 EXPECT_EQ(1u, value.data);
143 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
144
145 // check for the new attr_six
146 cookie = theme->GetAttribute(app::R::attr::attr_six, &value, &flags);
147 ASSERT_NE(kInvalidCookie, cookie);
148 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
149 EXPECT_EQ(6u, value.data);
150 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
151
152 // check for the old attr_five (force=true was not used).
153 cookie = theme->GetAttribute(app::R::attr::attr_five, &value, &flags);
154 ASSERT_NE(kInvalidCookie, cookie);
155 EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
156 EXPECT_EQ(app::R::string::string_one, value.data);
157 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
158}
159
160TEST_F(ThemeTest, MultipleThemesOverlaidForced) {
161 AssetManager2 assetmanager;
162 assetmanager.SetApkAssets({style_assets_.get()});
163
164 std::unique_ptr<Theme> theme = assetmanager.NewTheme();
165 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
166 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleThree, true /* force */));
167
168 Res_value value;
169 uint32_t flags;
170 ApkAssetsCookie cookie;
171
172 // attr_one is still here from the base.
173 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
174 ASSERT_NE(kInvalidCookie, cookie);
175 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
176 EXPECT_EQ(1u, value.data);
177 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
178
179 // check for the new attr_six
180 cookie = theme->GetAttribute(app::R::attr::attr_six, &value, &flags);
181 ASSERT_NE(kInvalidCookie, cookie);
182 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
183 EXPECT_EQ(6u, value.data);
184 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
185
186 // check for the new attr_five (force=true was used).
187 cookie = theme->GetAttribute(app::R::attr::attr_five, &value, &flags);
188 ASSERT_NE(kInvalidCookie, cookie);
189 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
190 EXPECT_EQ(5u, value.data);
191 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
192}
193
Adam Lesinskida431a22016-12-29 16:08:16 -0500194TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) {
195 AssetManager2 assetmanager;
196 assetmanager.SetApkAssets(
197 {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
198
199 std::unique_ptr<Theme> theme = assetmanager.NewTheme();
200 ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/));
201
202 Res_value value;
203 uint32_t flags;
204 ApkAssetsCookie cookie;
205
206 // The attribute should be resolved to the final value.
207 cookie = theme->GetAttribute(libclient::R::attr::foo, &value, &flags);
208 ASSERT_NE(kInvalidCookie, cookie);
209 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
210 EXPECT_EQ(700u, value.data);
211 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
212
213 // The reference should be resolved to a TYPE_REFERENCE.
214 cookie = theme->GetAttribute(libclient::R::attr::bar, &value, &flags);
215 ASSERT_NE(kInvalidCookie, cookie);
216 EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
217
218 // lib_one is assigned package ID 0x03.
Adam Lesinski929d6512017-01-16 19:11:19 -0800219 EXPECT_EQ(3u, get_package_id(value.data));
220 EXPECT_EQ(get_type_id(lib_one::R::string::foo), get_type_id(value.data));
221 EXPECT_EQ(get_entry_id(lib_one::R::string::foo), get_entry_id(value.data));
Adam Lesinskida431a22016-12-29 16:08:16 -0500222}
223
Adam Lesinski7ad11102016-10-28 16:39:15 -0700224TEST_F(ThemeTest, CopyThemeSameAssetManager) {
225 AssetManager2 assetmanager;
226 assetmanager.SetApkAssets({style_assets_.get()});
227
228 std::unique_ptr<Theme> theme_one = assetmanager.NewTheme();
229 ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne));
230
231 Res_value value;
232 uint32_t flags;
233 ApkAssetsCookie cookie;
234
235 // attr_one is still here from the base.
236 cookie = theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags);
237 ASSERT_NE(kInvalidCookie, cookie);
238 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
239 EXPECT_EQ(1u, value.data);
240 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
241
242 // attr_six is not here.
243 EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_six, &value, &flags));
244
245 std::unique_ptr<Theme> theme_two = assetmanager.NewTheme();
246 ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleThree));
247
248 // Copy the theme to theme_one.
249 ASSERT_TRUE(theme_one->SetTo(*theme_two));
250
251 // Clear theme_two to make sure we test that there WAS a copy.
252 theme_two->Clear();
253
254 // attr_one is now not here.
255 EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags));
256
257 // attr_six is now here because it was copied.
258 cookie = theme_one->GetAttribute(app::R::attr::attr_six, &value, &flags);
259 ASSERT_NE(kInvalidCookie, cookie);
260 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
261 EXPECT_EQ(6u, value.data);
262 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
263}
264
265TEST_F(ThemeTest, FailToCopyThemeWithDifferentAssetManager) {
266 AssetManager2 assetmanager_one;
267 assetmanager_one.SetApkAssets({style_assets_.get()});
268
269 AssetManager2 assetmanager_two;
270 assetmanager_two.SetApkAssets({style_assets_.get()});
271
272 auto theme_one = assetmanager_one.NewTheme();
273 ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne));
274
275 auto theme_two = assetmanager_two.NewTheme();
276 ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleTwo));
277
278 EXPECT_FALSE(theme_one->SetTo(*theme_two));
Adam Lesinski9d9cc622014-08-29 14:10:04 -0700279}
280
Adam Lesinski4c67a472016-11-10 16:43:59 -0800281} // namespace android