Theme_test.cpp revision 0c40524953f3d36a880f91183302a2ea5c722930
1/*
2 * Copyright (C) 2016 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/AssetManager2.h"
18
19#include "android-base/logging.h"
20
21#include "TestHelpers.h"
22#include "data/lib_one/R.h"
23#include "data/libclient/R.h"
24#include "data/styles/R.h"
25
26namespace app = com::android::app;
27namespace lib_one = com::android::lib_one;
28namespace libclient = com::android::libclient;
29
30namespace android {
31
32class 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_);
37
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_);
46  }
47
48 protected:
49  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_;
53};
54
55TEST_F(ThemeTest, EmptyTheme) {
56  AssetManager2 assetmanager;
57  assetmanager.SetApkAssets({style_assets_.get()});
58
59  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
60  EXPECT_EQ(0u, theme->GetChangingConfigurations());
61  EXPECT_EQ(&assetmanager, theme->GetAssetManager());
62
63  Res_value value;
64  uint32_t flags;
65  EXPECT_EQ(kInvalidCookie, theme->GetAttribute(app::R::attr::attr_one, &value, &flags));
66}
67
68TEST_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
193TEST_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
223TEST_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));
278}
279
280}  // namespace android
281