blob: 466b7d97da00719192c07db98be1060dedb1378a [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 >
Makoto Onuki22a931e2022-01-12 16:03:50 -080047 <processes>
48 <process android:process=":sub" android:name="com.foo.BazApplication" />
49 </processes>
Jake Whartonab660a72018-06-08 17:56:55 -040050 <activity android:name="com.foo.BarActivity"/>
51 <service android:name="com.foo.BarService"/>
52 <receiver android:name="com.foo.BarReceiver"/>
53 <provider android:name="com.foo.BarProvider"/>
54 </application>
55 <instrumentation android:name="com.foo.BarInstrumentation"/>
56 </manifest>)");
57
58 proguard::KeepSet set;
59 ASSERT_TRUE(proguard::CollectProguardRulesForManifest(manifest.get(), &set, false));
60
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070061 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
62 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
63 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarBackupAgent { <init>(); }"));
64 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarApplication { <init>(); }"));
Makoto Onuki22a931e2022-01-12 16:03:50 -080065 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BazApplication { <init>(); }"));
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070066 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarActivity { <init>(); }"));
67 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarService { <init>(); }"));
68 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
69 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
70 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
Martijn Coenen6c83e0c2019-03-06 15:06:17 +010071 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040072
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070073 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Whartone4bd1602018-06-12 09:39:14 -040074 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040075 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarBackupAgent { <init>(); }"));
Jake Whartoncfbc7672018-06-12 09:26:13 -040076 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarApplication { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040077 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarActivity { <init>(); }"));
78 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarService { <init>(); }"));
79 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
80 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
81 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
Martijn Coenen6c83e0c2019-03-06 15:06:17 +010082 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
Jake Whartonab660a72018-06-08 17:56:55 -040083}
84
Adam Lesinskif762df22017-06-26 16:39:03 -070085TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
86 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
87 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
88 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
89 android:name="com.foo.Bar"/>)");
90 layout->file.name = test::ParseNameOrDie("layout/foo");
91
92 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -070093 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070094
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070095 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
96 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -070097
Ryan Mitchell7e5236d2018-09-25 15:20:59 -070098 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -040099 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700100}
101
102TEST(ProguardRulesTest, FragmentClassRuleIsEmitted) {
103 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
104 std::unique_ptr<xml::XmlResource> layout =
105 test::BuildXmlDom(R"(<fragment class="com.foo.Bar"/>)");
106 layout->file.name = test::ParseNameOrDie("layout/foo");
107
108 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700109 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700110
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700111 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
112 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700113
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700114 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400115 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700116}
117
118TEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) {
119 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
120 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
121 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
122 android:name="com.foo.Baz"
123 class="com.foo.Bar"/>)");
124 layout->file.name = test::ParseNameOrDie("layout/foo");
125
126 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700127 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700128
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700129 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
130 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
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700133 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400134 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
135 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700136}
137
Jeremy Woods4bdc6982020-02-28 19:42:38 -0800138TEST(ProguardRulesTest, FragmentContainerViewNameRuleIsEmitted) {
139 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
140 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
141 <androidx.fragment.app.FragmentContainerView
142 xmlns:android="http://schemas.android.com/apk/res/android"
143 android:name="com.foo.Bar"/>)");
144 layout->file.name = test::ParseNameOrDie("layout/foo");
145
146 proguard::KeepSet set;
147 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
148
149 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
150 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
151
152 actual = GetKeepSetString(set, /** minimal_rules */ true);
153 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
154}
155
156TEST(ProguardRulesTest, FragmentContainerViewClassRuleIsEmitted) {
157 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
158 std::unique_ptr<xml::XmlResource> layout =
159 test::BuildXmlDom(R"(<androidx.fragment.app.FragmentContainerView class="com.foo.Bar"/>)");
160 layout->file.name = test::ParseNameOrDie("layout/foo");
161
162 proguard::KeepSet set;
163 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
164
165 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
166 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
167
168 actual = GetKeepSetString(set, /** minimal_rules */ true);
169 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
170}
171
172TEST(ProguardRulesTest, FragmentContainerViewNameAndClassRulesAreEmitted) {
173 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
174 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
175 <androidx.fragment.app.FragmentContainerView
176 xmlns:android="http://schemas.android.com/apk/res/android"
177 android:name="com.foo.Baz"
178 class="com.foo.Bar"/>)");
179 layout->file.name = test::ParseNameOrDie("layout/foo");
180
181 proguard::KeepSet set;
182 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
183
184 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
185 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
186 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
187
188 actual = GetKeepSetString(set, /** minimal_rules */ true);
189 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(); }"));
190 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(); }"));
191}
192
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700193TEST(ProguardRulesTest, NavigationFragmentNameAndClassRulesAreEmitted) {
194 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
195 .SetCompilationPackage("com.base").Build();
196 std::unique_ptr<xml::XmlResource> navigation = test::BuildXmlDom(R"(
197 <navigation
198 xmlns:android="http://schemas.android.com/apk/res/android"
199 xmlns:app="http://schemas.android.com/apk/res-auto">
200 <custom android:id="@id/foo"
201 android:name="com.package.Foo"/>
202 <fragment android:id="@id/bar"
203 android:name="com.package.Bar">
204 <nested android:id="@id/nested"
205 android:name=".Nested"/>
206 </fragment>
207 </navigation>
208 )");
209
210 navigation->file.name = test::ParseNameOrDie("navigation/graph.xml");
211
212 proguard::KeepSet set;
213 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), navigation.get(), &set));
214
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700215 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
216 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Foo { <init>(...); }"));
217 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Bar { <init>(...); }"));
218 EXPECT_THAT(actual, HasSubstr("-keep class com.base.Nested { <init>(...); }"));
219
220 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton420785e2018-06-11 15:40:48 -0400221 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Foo { <init>(...); }"));
222 EXPECT_THAT(actual, HasSubstr("-keep class com.package.Bar { <init>(...); }"));
223 EXPECT_THAT(actual, HasSubstr("-keep class com.base.Nested { <init>(...); }"));
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700224}
225
Adam Koskidc21dea2017-07-21 10:55:27 -0700226TEST(ProguardRulesTest, CustomViewRulesAreEmitted) {
227 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
228 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
229 <View xmlns:android="http://schemas.android.com/apk/res/android">
230 <com.foo.Bar />
231 </View>)");
232 layout->file.name = test::ParseNameOrDie("layout/foo");
233
234 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700235 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700236
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700237 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
238 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700239
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700240 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400241 EXPECT_THAT(actual, HasSubstr(
242 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700243}
244
245TEST(ProguardRulesTest, IncludedLayoutRulesAreConditional) {
246 std::unique_ptr<xml::XmlResource> bar_layout = test::BuildXmlDom(R"(
247 <View xmlns:android="http://schemas.android.com/apk/res/android">
248 <com.foo.Bar />
249 </View>)");
250 bar_layout->file.name = test::ParseNameOrDie("com.foo:layout/bar");
251
252 ResourceTable table;
253 StdErrDiagnostics errDiagnostics;
Ryan Mitchell1d008d12021-03-19 14:54:17 -0700254 table.AddResource(NewResourceBuilder(bar_layout->file.name)
255 .SetValue(util::make_unique<FileReference>())
256 .Build(),
257 &errDiagnostics);
Adam Koskidc21dea2017-07-21 10:55:27 -0700258
259 std::unique_ptr<IAaptContext> context =
260 test::ContextBuilder()
261 .SetCompilationPackage("com.foo")
262 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(&table))
263 .Build();
264
265 std::unique_ptr<xml::XmlResource> foo_layout = test::BuildXmlDom(R"(
266 <View xmlns:android="http://schemas.android.com/apk/res/android">
267 <include layout="@layout/bar" />
268 </View>)");
269 foo_layout->file.name = test::ParseNameOrDie("com.foo:layout/foo");
270
Ryan Mitchell326e35ff2021-04-12 07:50:42 -0700271 XmlReferenceLinker xml_linker(nullptr);
Adam Koskidc21dea2017-07-21 10:55:27 -0700272 ASSERT_TRUE(xml_linker.Consume(context.get(), bar_layout.get()));
273 ASSERT_TRUE(xml_linker.Consume(context.get(), foo_layout.get()));
274
275 proguard::KeepSet set = proguard::KeepSet(true);
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700276 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), bar_layout.get(), &set));
277 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), foo_layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700278
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700279 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
280 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
281 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
282 EXPECT_THAT(actual, HasSubstr("int foo"));
283 EXPECT_THAT(actual, HasSubstr("int bar"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700284
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700285 actual = GetKeepSetString(set, /** minimal_rules */ true);
Adam Koski09ef94e2017-11-10 11:15:55 -0800286 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400287 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700288 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700289 EXPECT_THAT(actual, HasSubstr("int foo"));
290 EXPECT_THAT(actual, HasSubstr("int bar"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700291}
292
293TEST(ProguardRulesTest, AliasedLayoutRulesAreConditional) {
294 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
295 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
296 <View xmlns:android="http://schemas.android.com/apk/res/android">
297 <com.foo.Bar />
298 </View>)");
299 layout->file.name = test::ParseNameOrDie("layout/foo");
300
301 proguard::KeepSet set = proguard::KeepSet(true);
302 set.AddReference({test::ParseNameOrDie("layout/bar"), {}}, layout->file.name);
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700303 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700304
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700305 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400306 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700307 "-keep class com.foo.Bar { <init>(...); }"));
308 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
309 EXPECT_THAT(actual, HasSubstr("int foo"));
310 EXPECT_THAT(actual, HasSubstr("int bar"));
311
312 actual = GetKeepSetString(set, /** minimal_rules */ true);
313 EXPECT_THAT(actual, HasSubstr(
314 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koski09ef94e2017-11-10 11:15:55 -0800315 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700316 EXPECT_THAT(actual, HasSubstr("int foo"));
317 EXPECT_THAT(actual, HasSubstr("int bar"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700318}
319
320TEST(ProguardRulesTest, NonLayoutReferencesAreUnconditional) {
321 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
322 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
323 <View xmlns:android="http://schemas.android.com/apk/res/android">
324 <com.foo.Bar />
325 </View>)");
326 layout->file.name = test::ParseNameOrDie("layout/foo");
327
328 proguard::KeepSet set = proguard::KeepSet(true);
329 set.AddReference({test::ParseNameOrDie("style/MyStyle"), {}}, layout->file.name);
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700330 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Koskidc21dea2017-07-21 10:55:27 -0700331
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700332 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
333 EXPECT_THAT(actual, Not(HasSubstr("-if")));
334 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700335
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700336 actual = GetKeepSetString(set, /** minimal_rules */ true);
Adam Koski09ef94e2017-11-10 11:15:55 -0800337 EXPECT_THAT(actual, Not(HasSubstr("-if")));
Jake Whartoncc65b8d2018-06-11 17:05:35 -0400338 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700339 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700340}
341
Adam Lesinskif762df22017-06-26 16:39:03 -0700342TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
343 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
344 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
345 <View xmlns:android="http://schemas.android.com/apk/res/android"
346 android:onClick="bar_method" />)");
347 layout->file.name = test::ParseNameOrDie("layout/foo");
348
349 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700350 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700351
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700352 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
Jake Wharton3001f032018-06-11 12:24:11 -0400353 EXPECT_THAT(actual, HasSubstr(
354 "-keepclassmembers class * { *** bar_method(android.view.View); }"));
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700355
356 actual = GetKeepSetString(set, /** minimal_rules */ true);
357 EXPECT_THAT(actual, HasSubstr(
358 "-keepclassmembers class * { *** bar_method(android.view.View); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700359}
360
361TEST(ProguardRulesTest, MenuRulesAreEmitted) {
362 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
363 std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
364 <menu xmlns:android="http://schemas.android.com/apk/res/android">
365 <item android:onClick="on_click"
366 android:actionViewClass="com.foo.Bar"
367 android:actionProviderClass="com.foo.Baz"
368 android:name="com.foo.Bat" />
369 </menu>)");
370 menu->file.name = test::ParseNameOrDie("menu/foo");
371
372 proguard::KeepSet set;
Ryan Mitchell9a2f6e62018-05-23 14:23:18 -0700373 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), menu.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700374
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700375 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
Jake Wharton3001f032018-06-11 12:24:11 -0400376 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700377 "-keepclassmembers class * { *** on_click(android.view.MenuItem); }"));
378 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
379 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(...); }"));
380 EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
381
382 actual = GetKeepSetString(set, /** minimal_rules */ true);
383 EXPECT_THAT(actual, HasSubstr(
384 "-keepclassmembers class * { *** on_click(android.view.MenuItem); }"));
Jake Wharton98100c32018-06-11 15:46:03 -0400385 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(android.content.Context); }"));
386 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz { <init>(android.content.Context); }"));
Adam Lesinskif762df22017-06-26 16:39:03 -0700387 EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
388}
389
Donald Chaidb19f512019-09-09 15:45:34 -0700390TEST(ProguardRulesTest, MenuRulesAreEmittedForActionClasses) {
391 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
392 std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
393 <menu xmlns:android="http://schemas.android.com/apk/res/android"
394 xmlns:app="http://schemas.android.com/apk/res-auto">
395 <item android:id="@+id/my_item"
396 app:actionViewClass="com.foo.Bar"
397 app:actionProviderClass="com.foo.Baz" />
398 </menu>)");
399 menu->file.name = test::ParseNameOrDie("menu/foo");
400
401 proguard::KeepSet set;
402 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), menu.get(), &set));
403
404 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
405 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar"));
406 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Baz"));
407}
408
Jake Wharton420785e2018-06-11 15:40:48 -0400409TEST(ProguardRulesTest, TransitionPathMotionRulesAreEmitted) {
410 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
411 std::unique_ptr<xml::XmlResource> transition = test::BuildXmlDom(R"(
412 <changeBounds>
413 <pathMotion class="com.foo.Bar"/>
414 </changeBounds>)");
415 transition->file.name = test::ParseNameOrDie("transition/foo");
416
417 proguard::KeepSet set;
418 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), transition.get(), &set));
419
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700420 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
421 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400422
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700423 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400424 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700425 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400426}
427
428TEST(ProguardRulesTest, TransitionRulesAreEmitted) {
429 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
430 std::unique_ptr<xml::XmlResource> transitionSet = test::BuildXmlDom(R"(
431 <transitionSet>
432 <transition class="com.foo.Bar"/>
433 </transitionSet>)");
434 transitionSet->file.name = test::ParseNameOrDie("transition/foo");
435
436 proguard::KeepSet set;
437 ASSERT_TRUE(proguard::CollectProguardRules(context.get(), transitionSet.get(), &set));
438
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700439 std::string actual = GetKeepSetString(set, /** minimal_rules */ false);
440 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400441
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700442 actual = GetKeepSetString(set, /** minimal_rules */ true);
Jake Wharton98100c32018-06-11 15:46:03 -0400443 EXPECT_THAT(actual, HasSubstr(
Ryan Mitchell7e5236d2018-09-25 15:20:59 -0700444 "-keep class com.foo.Bar { <init>(android.content.Context, android.util.AttributeSet); }"));
Jake Wharton420785e2018-06-11 15:40:48 -0400445}
446
Donald Chai44fa3422019-05-31 22:13:00 -0700447TEST(ProguardRulesTest, UsageLocationComparator) {
448 proguard::UsageLocation location1 = {{"pkg", ResourceType::kAttr, "x"}};
449 proguard::UsageLocation location2 = {{"pkg", ResourceType::kAttr, "y"}};
450
451 EXPECT_EQ(location1 < location2, true);
452 EXPECT_EQ(location2 < location1, false);
453}
454
Adam Lesinskif762df22017-06-26 16:39:03 -0700455} // namespace aapt