1 /*
2 * Copyright (C) 2019 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 "link/ResourceExcluder.h"
18
19 #include "ResourceTable.h"
20 #include "test/Test.h"
21
22 using ::aapt::test::HasValue;
23 using ::android::ConfigDescription;
24 using ::testing::Not;
25
26 namespace {
27
BuildArg(const std::string arg)28 ConfigDescription BuildArg(const std::string arg) {
29 ConfigDescription config_description;
30 ConfigDescription::Parse(arg, &config_description);
31 return config_description;
32 }
33
BuildArgList(const std::string arg)34 std::vector<ConfigDescription> BuildArgList(const std::string arg) {
35 ConfigDescription config_description;
36 ConfigDescription::Parse(arg, &config_description);
37 return { config_description };
38 }
39
40 } // namespace
41
42 namespace aapt {
43
TEST(ResourceExcluderTest,NonMatchConfigNotExcluded)44 TEST(ResourceExcluderTest, NonMatchConfigNotExcluded) {
45 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
46 ConfigDescription default_config;
47 auto fr_config = test::ParseConfigOrDie("fr");
48
49 std::unique_ptr<ResourceTable> table =
50 test::ResourceTableBuilder()
51 .AddString("android:string/test", ResourceId{}, default_config, "default")
52 .AddString("android:string/test", ResourceId{}, fr_config, "fr")
53 .Build();
54
55 auto args = BuildArgList("en");
56
57 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
58 EXPECT_THAT(table, HasValue("android:string/test", default_config));
59 EXPECT_THAT(table, HasValue("android:string/test", fr_config));
60 }
61
TEST(ResourceExcluderTest,ExactConfigExcluded)62 TEST(ResourceExcluderTest, ExactConfigExcluded) {
63 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
64 ConfigDescription default_config;
65 auto fr_config = test::ParseConfigOrDie("fr");
66
67 std::unique_ptr<ResourceTable> table =
68 test::ResourceTableBuilder()
69 .AddString("android:string/test", ResourceId{}, default_config, "default")
70 .AddString("android:string/test", ResourceId{}, fr_config, "fr")
71 .Build();
72
73 auto args = BuildArgList("fr");
74
75 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
76 EXPECT_THAT(table, HasValue("android:string/test", default_config));
77 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_config)));
78 }
79
TEST(ResourceExcluderTest,MoreSpecificConfigExcluded)80 TEST(ResourceExcluderTest, MoreSpecificConfigExcluded) {
81 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
82 ConfigDescription default_config;
83 auto fr_land_config = test::ParseConfigOrDie("fr-land");
84
85 std::unique_ptr<ResourceTable> table =
86 test::ResourceTableBuilder()
87 .AddString("android:string/test", ResourceId{}, default_config, "default")
88 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land")
89 .Build();
90
91 auto args = BuildArgList("fr");
92
93 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
94 EXPECT_THAT(table, HasValue("android:string/test", default_config));
95 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config)));
96 }
97
TEST(ResourceExcluderTest,MultipleMoreSpecificConfigExcluded)98 TEST(ResourceExcluderTest, MultipleMoreSpecificConfigExcluded) {
99 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
100 ConfigDescription default_config;
101 auto night_config = test::ParseConfigOrDie("night");
102 auto fr_config = test::ParseConfigOrDie("fr");
103 auto fr_land_config = test::ParseConfigOrDie("fr-land");
104 auto fr_night_config = test::ParseConfigOrDie("fr-night");
105
106 std::unique_ptr<ResourceTable> table =
107 test::ResourceTableBuilder()
108 .AddString("android:string/test", ResourceId{}, default_config, "default")
109 .AddString("android:string/test", ResourceId{}, night_config, "night")
110 .AddString("android:string/test", ResourceId{}, fr_config, "fr")
111 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land")
112 .AddString("android:string/test", ResourceId{}, fr_night_config, "fr-night")
113 .Build();
114
115 auto args = BuildArgList("fr");
116
117 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
118 EXPECT_THAT(table, HasValue("android:string/test", default_config));
119 EXPECT_THAT(table, HasValue("android:string/test", night_config));
120 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_config)));
121 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config)));
122 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_night_config)));
123 }
124
TEST(ResourceExcluderTest,MultipleConfigsExcluded)125 TEST(ResourceExcluderTest, MultipleConfigsExcluded) {
126 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
127 ConfigDescription default_config;
128 auto night_config = test::ParseConfigOrDie("night");
129 auto fr_config = test::ParseConfigOrDie("fr");
130 auto fr_land_config = test::ParseConfigOrDie("fr-land");
131 auto fr_night_config = test::ParseConfigOrDie("fr-night");
132
133 std::unique_ptr<ResourceTable> table =
134 test::ResourceTableBuilder()
135 .AddString("android:string/test", ResourceId{}, default_config, "default")
136 .AddString("android:string/test", ResourceId{}, night_config, "night")
137 .AddString("android:string/test", ResourceId{}, fr_config, "fr")
138 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land")
139 .AddString("android:string/test", ResourceId{}, fr_night_config, "fr-night")
140 .Build();
141
142 std::vector<ConfigDescription> args;
143 args.push_back(BuildArg("land"));
144 args.push_back(BuildArg("night"));
145
146 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
147 EXPECT_THAT(table, HasValue("android:string/test", default_config));
148 EXPECT_THAT(table, Not(HasValue("android:string/test", night_config)));
149 EXPECT_THAT(table, HasValue("android:string/test", fr_config));
150 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config)));
151 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_night_config)));
152 }
153
TEST(ResourceExcluderTest,LessSpecificConfigNotExcluded)154 TEST(ResourceExcluderTest, LessSpecificConfigNotExcluded) {
155 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
156 ConfigDescription default_config;
157 auto fr_config = test::ParseConfigOrDie("fr");
158 auto fr_land_config = test::ParseConfigOrDie("fr-land");
159
160 std::unique_ptr<ResourceTable> table =
161 test::ResourceTableBuilder()
162 .AddString("android:string/test", ResourceId{}, default_config, "default")
163 .AddString("android:string/test", ResourceId{}, fr_config, "fr")
164 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land")
165 .Build();
166
167 auto args = BuildArgList("fr-land");
168
169 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
170 EXPECT_THAT(table, HasValue("android:string/test", default_config));
171 EXPECT_THAT(table, HasValue("android:string/test", fr_config));
172 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config)));
173 }
174
TEST(ResourceExcluderTest,LowerPrecedenceStillExcludes)175 TEST(ResourceExcluderTest, LowerPrecedenceStillExcludes) {
176 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
177 ConfigDescription default_config;
178 auto fr_config = test::ParseConfigOrDie("fr");
179 auto fr_night_config = test::ParseConfigOrDie("fr-night");
180
181 std::unique_ptr<ResourceTable> table =
182 test::ResourceTableBuilder()
183 .AddString("android:string/test", ResourceId{}, default_config, "default")
184 .AddString("android:string/test", ResourceId{}, fr_config, "fr")
185 .AddString("android:string/test", ResourceId{}, fr_night_config, "fr-night")
186 .Build();
187
188 // "night" is lower precedence than "fr"
189 auto args = BuildArgList("night");
190
191 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
192 EXPECT_THAT(table, HasValue("android:string/test", default_config));
193 EXPECT_THAT(table, HasValue("android:string/test", fr_config));
194 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_night_config)));
195 }
196
TEST(ResourceExcluderTest,OnlyExcludesSpecificTier)197 TEST(ResourceExcluderTest, OnlyExcludesSpecificTier) {
198 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
199 ConfigDescription default_config;
200 auto mdpi_config = test::ParseConfigOrDie("mdpi");
201 auto hdpi_config = test::ParseConfigOrDie("hdpi");
202 auto xhdpi_config = test::ParseConfigOrDie("xhdpi");
203
204 std::unique_ptr<ResourceTable> table =
205 test::ResourceTableBuilder()
206 .AddString("android:string/test", ResourceId{}, default_config, "default")
207 .AddString("android:string/test", ResourceId{}, mdpi_config, "mdpi")
208 .AddString("android:string/test", ResourceId{}, hdpi_config, "hdpi")
209 .AddString("android:string/test", ResourceId{}, xhdpi_config, "xhdpi")
210 .Build();
211
212 auto args = BuildArgList("hdpi");
213
214 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get()));
215 EXPECT_THAT(table, HasValue("android:string/test", default_config));
216 EXPECT_THAT(table, HasValue("android:string/test", mdpi_config));
217 EXPECT_THAT(table, Not(HasValue("android:string/test", hdpi_config)));
218 EXPECT_THAT(table, HasValue("android:string/test", xhdpi_config));
219 }
220
221 } // namespace aapt
222