blob: f774e3a1245a6216b2cc800b66943872d4b9a811 [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 Kongstad5c541f62018-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
Adam Lesinskia693c4a2017-11-09 11:29:39 -080030std::string GetKeepSetString(const proguard::KeepSet& set) {
31 std::string out;
32 StringOutputStream sout(&out);
33 proguard::WriteKeepSet(set, &sout);
34 sout.Flush();
35 return out;
36}
37
Adam Lesinskif762df22017-06-26 16:39:03 -070038TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
39 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
40 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
41 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
42 android:name="com.foo.Bar"/>)");
43 layout->file.name = test::ParseNameOrDie("layout/foo");
44
45 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -070046 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070047
Adam Lesinskia693c4a2017-11-09 11:29:39 -080048 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -070049
Adam Lesinskif762df22017-06-26 16:39:03 -070050 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
51}
52
53TEST(ProguardRulesTest, FragmentClassRuleIsEmitted) {
54 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
55 std::unique_ptr<xml::XmlResource> layout =
56 test::BuildXmlDom(R"(<fragment class="com.foo.Bar"/>)");
57 layout->file.name = test::ParseNameOrDie("layout/foo");
58
59 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -070060 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070061
Adam Lesinskia693c4a2017-11-09 11:29:39 -080062 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -070063
Adam Lesinskif762df22017-06-26 16:39:03 -070064 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
65}
66
67TEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) {
68 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
69 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
70 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
71 android:name="com.foo.Baz"
72 class="com.foo.Bar"/>)");
73 layout->file.name = test::ParseNameOrDie("layout/foo");
74
75 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -070076 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070077
Adam Lesinskia693c4a2017-11-09 11:29:39 -080078 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -070079
Adam Lesinskif762df22017-06-26 16:39:03 -070080 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
81 EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
82}
83
Adam Koskidc21dea2017-07-21 10:55:27 -070084TEST(ProguardRulesTest, CustomViewRulesAreEmitted) {
85 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
86 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
87 <View xmlns:android="http://schemas.android.com/apk/res/android">
88 <com.foo.Bar />
89 </View>)");
90 layout->file.name = test::ParseNameOrDie("layout/foo");
91
92 proguard::KeepSet set;
93 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
94
Adam Lesinskia693c4a2017-11-09 11:29:39 -080095 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -070096
Adam Koskidc21dea2017-07-21 10:55:27 -070097 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
98}
99
100TEST(ProguardRulesTest, IncludedLayoutRulesAreConditional) {
101 std::unique_ptr<xml::XmlResource> bar_layout = test::BuildXmlDom(R"(
102 <View xmlns:android="http://schemas.android.com/apk/res/android">
103 <com.foo.Bar />
104 </View>)");
105 bar_layout->file.name = test::ParseNameOrDie("com.foo:layout/bar");
106
107 ResourceTable table;
108 StdErrDiagnostics errDiagnostics;
109 table.AddResource(bar_layout->file.name, ConfigDescription::DefaultConfig(), "",
110 util::make_unique<FileReference>(), &errDiagnostics);
111
112 std::unique_ptr<IAaptContext> context =
113 test::ContextBuilder()
114 .SetCompilationPackage("com.foo")
115 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(&table))
116 .Build();
117
118 std::unique_ptr<xml::XmlResource> foo_layout = test::BuildXmlDom(R"(
119 <View xmlns:android="http://schemas.android.com/apk/res/android">
120 <include layout="@layout/bar" />
121 </View>)");
122 foo_layout->file.name = test::ParseNameOrDie("com.foo:layout/foo");
123
124 XmlReferenceLinker xml_linker;
125 ASSERT_TRUE(xml_linker.Consume(context.get(), bar_layout.get()));
126 ASSERT_TRUE(xml_linker.Consume(context.get(), foo_layout.get()));
127
128 proguard::KeepSet set = proguard::KeepSet(true);
129 ASSERT_TRUE(proguard::CollectProguardRules(bar_layout.get(), &set));
130 ASSERT_TRUE(proguard::CollectProguardRules(foo_layout.get(), &set));
131
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800132 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -0700133
Adam Koski09ef94e2017-11-10 11:15:55 -0800134 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800135 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700136 EXPECT_THAT(actual, HasSubstr("int foo"));
137 EXPECT_THAT(actual, HasSubstr("int bar"));
138 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
139}
140
141TEST(ProguardRulesTest, AliasedLayoutRulesAreConditional) {
142 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
143 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
144 <View xmlns:android="http://schemas.android.com/apk/res/android">
145 <com.foo.Bar />
146 </View>)");
147 layout->file.name = test::ParseNameOrDie("layout/foo");
148
149 proguard::KeepSet set = proguard::KeepSet(true);
150 set.AddReference({test::ParseNameOrDie("layout/bar"), {}}, layout->file.name);
151 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
152
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800153 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -0700154
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800155 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koski09ef94e2017-11-10 11:15:55 -0800156 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700157 EXPECT_THAT(actual, HasSubstr("int foo"));
158 EXPECT_THAT(actual, HasSubstr("int bar"));
159 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
160}
161
162TEST(ProguardRulesTest, NonLayoutReferencesAreUnconditional) {
163 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
164 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
165 <View xmlns:android="http://schemas.android.com/apk/res/android">
166 <com.foo.Bar />
167 </View>)");
168 layout->file.name = test::ParseNameOrDie("layout/foo");
169
170 proguard::KeepSet set = proguard::KeepSet(true);
171 set.AddReference({test::ParseNameOrDie("style/MyStyle"), {}}, layout->file.name);
172 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
173
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800174 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -0700175
Adam Koski09ef94e2017-11-10 11:15:55 -0800176 EXPECT_THAT(actual, Not(HasSubstr("-if")));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800177 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700178}
179
Adam Lesinskif762df22017-06-26 16:39:03 -0700180TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
181 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
182 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
183 <View xmlns:android="http://schemas.android.com/apk/res/android"
184 android:onClick="bar_method" />)");
185 layout->file.name = test::ParseNameOrDie("layout/foo");
186
187 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -0700188 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700189
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800190 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -0700191
Adam Lesinskif762df22017-06-26 16:39:03 -0700192 EXPECT_THAT(actual, HasSubstr("bar_method"));
193}
194
195TEST(ProguardRulesTest, MenuRulesAreEmitted) {
196 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
197 std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
198 <menu xmlns:android="http://schemas.android.com/apk/res/android">
199 <item android:onClick="on_click"
200 android:actionViewClass="com.foo.Bar"
201 android:actionProviderClass="com.foo.Baz"
202 android:name="com.foo.Bat" />
203 </menu>)");
204 menu->file.name = test::ParseNameOrDie("menu/foo");
205
206 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -0700207 ASSERT_TRUE(proguard::CollectProguardRules(menu.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700208
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800209 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -0700210
Adam Lesinskif762df22017-06-26 16:39:03 -0700211 EXPECT_THAT(actual, HasSubstr("on_click"));
212 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
213 EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
214 EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
215}
216
217} // namespace aapt