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