blob: b7dfec3a6b2838a38aa329ee3ec8ffbbda5d87d3 [file] [log] [blame]
Adam Lesinskif762df22017-06-26 16:39:03 -07001/*
2 * Copyright (C) 2017 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 "java/ProguardRules.h"
Adam Koskidc21dea2017-07-21 10:55:27 -070018#include "link/Linkers.h"
Adam Lesinskif762df22017-06-26 16:39:03 -070019
Adam Lesinskia693c4a2017-11-09 11:29:39 -080020#include "io/StringStream.h"
Adam Lesinskif762df22017-06-26 16:39:03 -070021#include "test/Test.h"
22
Adam Lesinskia693c4a2017-11-09 11:29:39 -080023using ::aapt::io::StringOutputStream;
MÃ¥rten Kongstad24c9aa62018-06-20 08:46:41 +020024using ::android::ConfigDescription;
Adam Lesinskif762df22017-06-26 16:39:03 -070025using ::testing::HasSubstr;
26using ::testing::Not;
27
28namespace aapt {
29
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070030std::string GetKeepSetString(const proguard::KeepSet& set, bool minimal_rules) {
Adam Lesinskia693c4a2017-11-09 11:29:39 -080031 std::string out;
32 StringOutputStream sout(&out);
Jean-Luc Coelho181cbfd2019-11-27 12:37:48 -080033 proguard::WriteKeepSet(set, &sout, minimal_rules, false);
Adam Lesinskia693c4a2017-11-09 11:29:39 -080034 sout.Flush();
35 return out;
36}
37
Jake Whartonab660a72018-06-08 17:56:55 -040038TEST(ProguardRulesTest, ManifestRuleDefaultConstructorOnly) {
39 std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
40 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
Jake Whartoncfbc7672018-06-12 09:26:13 -040041 <application
Jake Whartone4bd1602018-06-12 09:39:14 -040042 android:appComponentFactory="com.foo.BarAppComponentFactory"
Jake Whartoncfbc7672018-06-12 09:26:13 -040043 android:backupAgent="com.foo.BarBackupAgent"
44 android:name="com.foo.BarApplication"
Martijn Coenen6c83e0c2019-03-06 15:06:17 +010045 android:zygotePreloadName="com.foo.BarZygotePreload"
Jake Whartoncfbc7672018-06-12 09:26:13 -040046 >
Jake Whartonab660a72018-06-08 17:56:55 -040047 <activity android:name="com.foo.BarActivity"/>
48 <service android:name="com.foo.BarService"/>
49 <receiver android:name="com.foo.BarReceiver"/>
50 <provider android:name="com.foo.BarProvider"/>
51 </application>
52 <instrumentation android:name="com.foo.BarInstrumentation"/>
53 </manifest>)");
54
55 proguard::KeepSet set;
56 ASSERT_TRUE(proguard::CollectProguardRulesForManifest(manifest.get(), &set, false));
57
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070058 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
59 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
60 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarBackupAgent { <init>(); }"));
61 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarApplication { <init>(); }"));
62 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarActivity { <init>(); }"));
63 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarService { <init>(); }"));
64 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
65 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
66 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
Martijn Coenen6c83e0c2019-03-06 15:06:17 +010067 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040068
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070069 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Whartone4bd1602018-06-12 09:39:14 -040070 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040071 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarBackupAgent { <init>(); }"));
Jake Whartoncfbc7672018-06-12 09:26:13 -040072 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarApplication { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040073 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarActivity { <init>(); }"));
74 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarService { <init>(); }"));
75 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
76 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
77 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
Martijn Coenen6c83e0c2019-03-06 15:06:17 +010078 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040079}
80
Adam Lesinskif762df22017-06-26 16:39:03 -070081TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
82 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
83 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
84 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
85 android:name="com.foo.Bar"/>)");
86 layout->file.name = test::ParseNameOrDie("layout/foo");
87
88 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -070089 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070090
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070091 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
92 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -070093
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070094 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -040095 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -070096}
97
98TEST(ProguardRulesTest, FragmentClassRuleIsEmitted) {
99 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
100 std::unique_ptr<xml::XmlResource> layout =
101 test::BuildXmlDom(R"(<fragment class="com.foo.Bar"/>)");
102 layout->file.name = test::ParseNameOrDie("layout/foo");
103
104 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700105 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700106
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700107 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
108 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700109
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700110 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400111 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700112}
113
114TEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) {
115 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
116 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
117 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
118 android:name="com.foo.Baz"
119 class="com.foo.Bar"/>)");
120 layout->file.name = test::ParseNameOrDie("layout/foo");
121
122 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700123 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700124
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700125 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
126 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
127 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700128
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700129 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400130 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
131 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700132}
133
Jeremy Woods4bdc6982020-02-28 19:42:38 -0800134TEST(ProguardRulesTest, FragmentContainerViewNameRuleIsEmitted) {
135 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
136 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
137 <androidx.fragment.app.FragmentContainerView
138 xmlns:android="http://schemas.android.com/apk/res/android"
139 android:name="com.foo.Bar"/>)");
140 layout->file.name = test::ParseNameOrDie("layout/foo");
141
142 proguard::KeepSet set;
143 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
144
145 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
146 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
147
148 actual = GetKeepSetString(set, /** minimal_rules */ true);
149 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
150}
151
152TEST(ProguardRulesTest, FragmentContainerViewClassRuleIsEmitted) {
153 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
154 std::unique_ptr<xml::XmlResource> layout =
155 test::BuildXmlDom(R"(<androidx.fragment.app.FragmentContainerView class="com.foo.Bar"/>)");
156 layout->file.name = test::ParseNameOrDie("layout/foo");
157
158 proguard::KeepSet set;
159 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
160
161 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
162 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
163
164 actual = GetKeepSetString(set, /** minimal_rules */ true);
165 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
166}
167
168TEST(ProguardRulesTest, FragmentContainerViewNameAndClassRulesAreEmitted) {
169 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
170 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
171 <androidx.fragment.app.FragmentContainerView
172 xmlns:android="http://schemas.android.com/apk/res/android"
173 android:name="com.foo.Baz"
174 class="com.foo.Bar"/>)");
175 layout->file.name = test::ParseNameOrDie("layout/foo");
176
177 proguard::KeepSet set;
178 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
179
180 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
181 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
182 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
183
184 actual = GetKeepSetString(set, /** minimal_rules */ true);
185 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
186 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }"));
187}
188
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700189TEST(ProguardRulesTest, NavigationFragmentNameAndClassRulesAreEmitted) {
190 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
191 .SetCompilationPackage("com.base").Build();
192 std::unique_ptr<xml::XmlResource> navigation = test::BuildXmlDom(R"(
193 <navigation
194 xmlns:android="http://schemas.android.com/apk/res/android"
195 xmlns:app="http://schemas.android.com/apk/res-auto">
196 <custom android:id="@id/foo"
197 android:name="com.package.Foo"/>
198 <fragment android:id="@id/bar"
199 android:name="com.package.Bar">
200 <nested android:id="@id/nested"
201 android:name=".Nested"/>
202 </fragment>
203 </navigation>
204 )");
205
206 navigation->file.name = test::ParseNameOrDie("navigation/graph.xml");
207
208 proguard::KeepSet set;
209 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), navigation.get(), &set));
210
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700211 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
212 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Foo { <init>(...); }"));
213 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Bar { <init>(...); }"));
214 EXPECT_THAT(actual, HasSubstr("-keep class com.base.Nested { <init>(...); }"));
215
216 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton420785e2018-06-11 15:40:48 -0400217 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Foo { <init>(...); }"));
218 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Bar { <init>(...); }"));
219 EXPECT_THAT(actual, HasSubstr("-keep class com.base.Nested { <init>(...); }"));
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700220}
221
Adam Koskidc21dea2017-07-21 10:55:27 -0700222TEST(ProguardRulesTest, CustomViewRulesAreEmitted) {
223 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
224 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
225 <View xmlns:android="http://schemas.android.com/apk/res/android">
226 <com.foo.Bar />
227 </View>)");
228 layout->file.name = test::ParseNameOrDie("layout/foo");
229
230 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700231 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700232
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700233 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
234 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700235
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700236 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400237 EXPECT_THAT(actual, HasSubstr(
238 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700239}
240
241TEST(ProguardRulesTest, IncludedLayoutRulesAreConditional) {
242 std::unique_ptr<xml::XmlResource> bar_layout = test::BuildXmlDom(R"(
243 <View xmlns:android="http://schemas.android.com/apk/res/android">
244 <com.foo.Bar />
245 </View>)");
246 bar_layout->file.name = test::ParseNameOrDie("com.foo:layout/bar");
247
248 ResourceTable table;
249 StdErrDiagnostics errDiagnostics;
Ryan Mitchell1d008d12021-03-19 14:54:17 -0700250 table.AddResource(NewResourceBuilder(bar_layout->file.name)
251 .SetValue(util::make_unique<FileReference>())
252 .Build(),
253 &errDiagnostics);
Adam Koskidc21dea2017-07-21 10:55:27 -0700254
255 std::unique_ptr<IAaptContext> context =
256 test::ContextBuilder()
257 .SetCompilationPackage("com.foo")
258 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(&table))
259 .Build();
260
261 std::unique_ptr<xml::XmlResource> foo_layout = test::BuildXmlDom(R"(
262 <View xmlns:android="http://schemas.android.com/apk/res/android">
263 <include layout="@layout/bar" />
264 </View>)");
265 foo_layout->file.name = test::ParseNameOrDie("com.foo:layout/foo");
266
267 XmlReferenceLinker xml_linker;
268 ASSERT_TRUE(xml_linker.Consume(context.get(), bar_layout.get()));
269 ASSERT_TRUE(xml_linker.Consume(context.get(), foo_layout.get()));
270
271 proguard::KeepSet set = proguard::KeepSet(true);
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700272 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), bar_layout.get(), &set));
273 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), foo_layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700274
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700275 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
276 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
277 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
278 EXPECT_THAT(actual, HasSubstr("int foo"));
279 EXPECT_THAT(actual, HasSubstr("int bar"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700280
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700281 actual = GetKeepSetString(set, /** minimal_rules */ true);
Adam Koski09ef94e2017-11-10 11:15:55 -0800282 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400283 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700284 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700285 EXPECT_THAT(actual, HasSubstr("int foo"));
286 EXPECT_THAT(actual, HasSubstr("int bar"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700287}
288
289TEST(ProguardRulesTest, AliasedLayoutRulesAreConditional) {
290 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
291 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
292 <View xmlns:android="http://schemas.android.com/apk/res/android">
293 <com.foo.Bar />
294 </View>)");
295 layout->file.name = test::ParseNameOrDie("layout/foo");
296
297 proguard::KeepSet set = proguard::KeepSet(true);
298 set.AddReference({test::ParseNameOrDie("layout/bar"), {}}, layout->file.name);
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700299 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700300
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700301 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400302 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700303 "-keep class com.foo.Bar { <init>(...); }"));
304 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
305 EXPECT_THAT(actual, HasSubstr("int foo"));
306 EXPECT_THAT(actual, HasSubstr("int bar"));
307
308 actual = GetKeepSetString(set, /** minimal_rules */ true);
309 EXPECT_THAT(actual, HasSubstr(
310 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koski09ef94e2017-11-10 11:15:55 -0800311 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700312 EXPECT_THAT(actual, HasSubstr("int foo"));
313 EXPECT_THAT(actual, HasSubstr("int bar"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700314}
315
316TEST(ProguardRulesTest, NonLayoutReferencesAreUnconditional) {
317 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
318 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
319 <View xmlns:android="http://schemas.android.com/apk/res/android">
320 <com.foo.Bar />
321 </View>)");
322 layout->file.name = test::ParseNameOrDie("layout/foo");
323
324 proguard::KeepSet set = proguard::KeepSet(true);
325 set.AddReference({test::ParseNameOrDie("style/MyStyle"), {}}, layout->file.name);
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700326 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700327
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700328 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
329 EXPECT_THAT(actual, Not(HasSubstr("-if")));
330 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700331
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700332 actual = GetKeepSetString(set, /** minimal_rules */ true);
Adam Koski09ef94e2017-11-10 11:15:55 -0800333 EXPECT_THAT(actual, Not(HasSubstr("-if")));
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400334 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700335 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700336}
337
Adam Lesinskif762df22017-06-26 16:39:03 -0700338TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
339 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
340 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
341 <View xmlns:android="http://schemas.android.com/apk/res/android"
342 android:onClick="bar_method" />)");
343 layout->file.name = test::ParseNameOrDie("layout/foo");
344
345 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700346 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700347
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700348 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
Jake Wharton3001f032018-06-11 12:24:11 -0400349 EXPECT_THAT(actual, HasSubstr(
350 "-keepclassmembers class * { *** bar_method(android.view.View); }"));
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700351
352 actual = GetKeepSetString(set, /** minimal_rules */ true);
353 EXPECT_THAT(actual, HasSubstr(
354 "-keepclassmembers class * { *** bar_method(android.view.View); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700355}
356
357TEST(ProguardRulesTest, MenuRulesAreEmitted) {
358 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
359 std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
360 <menu xmlns:android="http://schemas.android.com/apk/res/android">
361 <item android:onClick="on_click"
362 android:actionViewClass="com.foo.Bar"
363 android:actionProviderClass="com.foo.Baz"
364 android:name="com.foo.Bat" />
365 </menu>)");
366 menu->file.name = test::ParseNameOrDie("menu/foo");
367
368 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700369 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), menu.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700370
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700371 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
Jake Wharton3001f032018-06-11 12:24:11 -0400372 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700373 "-keepclassmembers class * { *** on_click(android.view.MenuItem); }"));
374 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
375 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
376 EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
377
378 actual = GetKeepSetString(set, /** minimal_rules */ true);
379 EXPECT_THAT(actual, HasSubstr(
380 "-keepclassmembers class * { *** on_click(android.view.MenuItem); }"));
Jake Wharton98100c32018-06-11 15:46:03 -0400381 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(android.content.Context); }"));
382 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(android.content.Context); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700383 EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
384}
385
Donald Chaidb19f512019-09-09 15:45:34 -0700386TEST(ProguardRulesTest, MenuRulesAreEmittedForActionClasses) {
387 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
388 std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
389 <menu xmlns:android="http://schemas.android.com/apk/res/android"
390 xmlns:app="http://schemas.android.com/apk/res-auto">
391 <item android:id="@+id/my_item"
392 app:actionViewClass="com.foo.Bar"
393 app:actionProviderClass="com.foo.Baz" />
394 </menu>)");
395 menu->file.name = test::ParseNameOrDie("menu/foo");
396
397 proguard::KeepSet set;
398 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), menu.get(), &set));
399
400 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
401 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar"));
402 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz"));
403}
404
Jake Wharton420785e2018-06-11 15:40:48 -0400405TEST(ProguardRulesTest, TransitionPathMotionRulesAreEmitted) {
406 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
407 std::unique_ptr<xml::XmlResource> transition = test::BuildXmlDom(R"(
408 <changeBounds>
409 <pathMotion class="com.foo.Bar"/>
410 </changeBounds>)");
411 transition->file.name = test::ParseNameOrDie("transition/foo");
412
413 proguard::KeepSet set;
414 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), transition.get(), &set));
415
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700416 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
417 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400418
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700419 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400420 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700421 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400422}
423
424TEST(ProguardRulesTest, TransitionRulesAreEmitted) {
425 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
426 std::unique_ptr<xml::XmlResource> transitionSet = test::BuildXmlDom(R"(
427 <transitionSet>
428 <transition class="com.foo.Bar"/>
429 </transitionSet>)");
430 transitionSet->file.name = test::ParseNameOrDie("transition/foo");
431
432 proguard::KeepSet set;
433 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), transitionSet.get(), &set));
434
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700435 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
436 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400437
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700438 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400439 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700440 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400441}
442
Donald Chai44fa3422019-05-31 22:13:00 -0700443TEST(ProguardRulesTest, UsageLocationComparator) {
444 proguard::UsageLocation location1 = {{"pkg", ResourceType::kAttr, "x"}};
445 proguard::UsageLocation location2 = {{"pkg", ResourceType::kAttr, "y"}};
446
447 EXPECT_EQ(location1 < location2, true);
448 EXPECT_EQ(location2 < location1, false);
449}
450
Adam Lesinskif762df22017-06-26 16:39:03 -0700451} // namespace aapt