blob: 37d1a5fbaeb8ac573f9f354a45f3f37adf013bc4 [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;
Adam Lesinskif762df22017-06-26 16:39:03 -070024using ::testing::HasSubstr;
25using ::testing::Not;
26
27namespace aapt {
28
Adam Lesinskia693c4a2017-11-09 11:29:39 -080029std::string GetKeepSetString(const proguard::KeepSet& set) {
30 std::string out;
31 StringOutputStream sout(&out);
32 proguard::WriteKeepSet(set, &sout);
33 sout.Flush();
34 return out;
35}
36
Adam Lesinskif762df22017-06-26 16:39:03 -070037TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
38 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
39 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
40 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
41 android:name="com.foo.Bar"/>)");
42 layout->file.name = test::ParseNameOrDie("layout/foo");
43
44 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -070045 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070046
Adam Lesinskia693c4a2017-11-09 11:29:39 -080047 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -070048
Adam Lesinskif762df22017-06-26 16:39:03 -070049 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
50}
51
52TEST(ProguardRulesTest, FragmentClassRuleIsEmitted) {
53 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
54 std::unique_ptr<xml::XmlResource> layout =
55 test::BuildXmlDom(R"(<fragment class="com.foo.Bar"/>)");
56 layout->file.name = test::ParseNameOrDie("layout/foo");
57
58 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -070059 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070060
Adam Lesinskia693c4a2017-11-09 11:29:39 -080061 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -070062
Adam Lesinskif762df22017-06-26 16:39:03 -070063 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
64}
65
66TEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) {
67 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
68 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
69 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
70 android:name="com.foo.Baz"
71 class="com.foo.Bar"/>)");
72 layout->file.name = test::ParseNameOrDie("layout/foo");
73
74 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -070075 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -070076
Adam Lesinskia693c4a2017-11-09 11:29:39 -080077 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -070078
Adam Lesinskif762df22017-06-26 16:39:03 -070079 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
80 EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
81}
82
Adam Koskidc21dea2017-07-21 10:55:27 -070083TEST(ProguardRulesTest, CustomViewRulesAreEmitted) {
84 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
85 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
86 <View xmlns:android="http://schemas.android.com/apk/res/android">
87 <com.foo.Bar />
88 </View>)");
89 layout->file.name = test::ParseNameOrDie("layout/foo");
90
91 proguard::KeepSet set;
92 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
93
Adam Lesinskia693c4a2017-11-09 11:29:39 -080094 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -070095
Adam Koskidc21dea2017-07-21 10:55:27 -070096 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
97}
98
99TEST(ProguardRulesTest, IncludedLayoutRulesAreConditional) {
100 std::unique_ptr<xml::XmlResource> bar_layout = test::BuildXmlDom(R"(
101 <View xmlns:android="http://schemas.android.com/apk/res/android">
102 <com.foo.Bar />
103 </View>)");
104 bar_layout->file.name = test::ParseNameOrDie("com.foo:layout/bar");
105
106 ResourceTable table;
107 StdErrDiagnostics errDiagnostics;
108 table.AddResource(bar_layout->file.name, ConfigDescription::DefaultConfig(), "",
109 util::make_unique<FileReference>(), &errDiagnostics);
110
111 std::unique_ptr<IAaptContext> context =
112 test::ContextBuilder()
113 .SetCompilationPackage("com.foo")
114 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(&table))
115 .Build();
116
117 std::unique_ptr<xml::XmlResource> foo_layout = test::BuildXmlDom(R"(
118 <View xmlns:android="http://schemas.android.com/apk/res/android">
119 <include layout="@layout/bar" />
120 </View>)");
121 foo_layout->file.name = test::ParseNameOrDie("com.foo:layout/foo");
122
123 XmlReferenceLinker xml_linker;
124 ASSERT_TRUE(xml_linker.Consume(context.get(), bar_layout.get()));
125 ASSERT_TRUE(xml_linker.Consume(context.get(), foo_layout.get()));
126
127 proguard::KeepSet set = proguard::KeepSet(true);
128 ASSERT_TRUE(proguard::CollectProguardRules(bar_layout.get(), &set));
129 ASSERT_TRUE(proguard::CollectProguardRules(foo_layout.get(), &set));
130
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800131 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -0700132
Adam Koski09ef94e2017-11-10 11:15:55 -0800133 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800134 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700135 EXPECT_THAT(actual, HasSubstr("int foo"));
136 EXPECT_THAT(actual, HasSubstr("int bar"));
137 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
138}
139
140TEST(ProguardRulesTest, AliasedLayoutRulesAreConditional) {
141 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
142 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
143 <View xmlns:android="http://schemas.android.com/apk/res/android">
144 <com.foo.Bar />
145 </View>)");
146 layout->file.name = test::ParseNameOrDie("layout/foo");
147
148 proguard::KeepSet set = proguard::KeepSet(true);
149 set.AddReference({test::ParseNameOrDie("layout/bar"), {}}, layout->file.name);
150 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
151
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800152 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -0700153
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800154 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koski09ef94e2017-11-10 11:15:55 -0800155 EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700156 EXPECT_THAT(actual, HasSubstr("int foo"));
157 EXPECT_THAT(actual, HasSubstr("int bar"));
158 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
159}
160
161TEST(ProguardRulesTest, NonLayoutReferencesAreUnconditional) {
162 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
163 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
164 <View xmlns:android="http://schemas.android.com/apk/res/android">
165 <com.foo.Bar />
166 </View>)");
167 layout->file.name = test::ParseNameOrDie("layout/foo");
168
169 proguard::KeepSet set = proguard::KeepSet(true);
170 set.AddReference({test::ParseNameOrDie("style/MyStyle"), {}}, layout->file.name);
171 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
172
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800173 std::string actual = GetKeepSetString(set);
Adam Koskidc21dea2017-07-21 10:55:27 -0700174
Adam Koski09ef94e2017-11-10 11:15:55 -0800175 EXPECT_THAT(actual, Not(HasSubstr("-if")));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800176 EXPECT_THAT(actual, HasSubstr("-keep class com.foo.Bar { <init>(...); }"));
Adam Koskidc21dea2017-07-21 10:55:27 -0700177}
178
Adam Lesinskif762df22017-06-26 16:39:03 -0700179TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
180 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
181 std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
182 <View xmlns:android="http://schemas.android.com/apk/res/android"
183 android:onClick="bar_method" />)");
184 layout->file.name = test::ParseNameOrDie("layout/foo");
185
186 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -0700187 ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700188
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800189 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -0700190
Adam Lesinskif762df22017-06-26 16:39:03 -0700191 EXPECT_THAT(actual, HasSubstr("bar_method"));
192}
193
194TEST(ProguardRulesTest, MenuRulesAreEmitted) {
195 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
196 std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
197 <menu xmlns:android="http://schemas.android.com/apk/res/android">
198 <item android:onClick="on_click"
199 android:actionViewClass="com.foo.Bar"
200 android:actionProviderClass="com.foo.Baz"
201 android:name="com.foo.Bat" />
202 </menu>)");
203 menu->file.name = test::ParseNameOrDie("menu/foo");
204
205 proguard::KeepSet set;
Adam Koskidc21dea2017-07-21 10:55:27 -0700206 ASSERT_TRUE(proguard::CollectProguardRules(menu.get(), &set));
Adam Lesinskif762df22017-06-26 16:39:03 -0700207
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800208 std::string actual = GetKeepSetString(set);
Adam Lesinskif762df22017-06-26 16:39:03 -0700209
Adam Lesinskif762df22017-06-26 16:39:03 -0700210 EXPECT_THAT(actual, HasSubstr("on_click"));
211 EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
212 EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
213 EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
214}
215
216} // namespace aapt