ProguardRules_test.cpp revision dc21dea9b8b1157a4a9347b68301da4307c51168
1f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski/*
2f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * Copyright (C) 2017 The Android Open Source Project
3f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski *
4f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * you may not use this file except in compliance with the License.
6f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * You may obtain a copy of the License at
7f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski *
8f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski *
10f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * See the License for the specific language governing permissions and
14f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski * limitations under the License.
15f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski */
16f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
17f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski#include "java/ProguardRules.h"
18dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski#include "link/Linkers.h"
19f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
20f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski#include "test/Test.h"
21f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
22f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinskiusing ::testing::HasSubstr;
23f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinskiusing ::testing::Not;
24f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
25f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinskinamespace aapt {
26f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
27f762df257574231ffd08679a69e9cf62fe143dcdAdam LesinskiTEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
28f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
29f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
30f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      <fragment xmlns:android="http://schemas.android.com/apk/res/android"
31f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          android:name="com.foo.Bar"/>)");
32f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  layout->file.name = test::ParseNameOrDie("layout/foo");
33f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
34f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  proguard::KeepSet set;
35dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
36f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
37f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::stringstream out;
38f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
39f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
40f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::string actual = out.str();
41f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
42f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski}
43f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
44f762df257574231ffd08679a69e9cf62fe143dcdAdam LesinskiTEST(ProguardRulesTest, FragmentClassRuleIsEmitted) {
45f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
46f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<xml::XmlResource> layout =
47f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      test::BuildXmlDom(R"(<fragment class="com.foo.Bar"/>)");
48f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  layout->file.name = test::ParseNameOrDie("layout/foo");
49f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
50f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  proguard::KeepSet set;
51dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
52f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
53f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::stringstream out;
54f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
55f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
56f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::string actual = out.str();
57f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
58f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski}
59f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
60f762df257574231ffd08679a69e9cf62fe143dcdAdam LesinskiTEST(ProguardRulesTest, FragmentNameAndClassRulesAreEmitted) {
61f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
62f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
63f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      <fragment xmlns:android="http://schemas.android.com/apk/res/android"
64f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          android:name="com.foo.Baz"
65f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          class="com.foo.Bar"/>)");
66f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  layout->file.name = test::ParseNameOrDie("layout/foo");
67f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
68f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  proguard::KeepSet set;
69dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
70f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
71f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::stringstream out;
72f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
73f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
74f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::string actual = out.str();
75f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
76f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
77f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski}
78f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
79dc21dea9b8b1157a4a9347b68301da4307c51168Adam KoskiTEST(ProguardRulesTest, CustomViewRulesAreEmitted) {
80dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
81dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
82dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      <View xmlns:android="http://schemas.android.com/apk/res/android">
83dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski        <com.foo.Bar />
84dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      </View>)");
85dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  layout->file.name = test::ParseNameOrDie("layout/foo");
86dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
87dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  proguard::KeepSet set;
88dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
89dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
90dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::stringstream out;
91dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
92dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
93dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::string actual = out.str();
94dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
95dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski}
96dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
97dc21dea9b8b1157a4a9347b68301da4307c51168Adam KoskiTEST(ProguardRulesTest, IncludedLayoutRulesAreConditional) {
98dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<xml::XmlResource> bar_layout = test::BuildXmlDom(R"(
99dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      <View xmlns:android="http://schemas.android.com/apk/res/android">
100dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski        <com.foo.Bar />
101dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      </View>)");
102dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  bar_layout->file.name = test::ParseNameOrDie("com.foo:layout/bar");
103dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
104dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ResourceTable table;
105dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  StdErrDiagnostics errDiagnostics;
106dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  table.AddResource(bar_layout->file.name, ConfigDescription::DefaultConfig(), "",
107dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski                    util::make_unique<FileReference>(), &errDiagnostics);
108dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
109dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<IAaptContext> context =
110dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      test::ContextBuilder()
111dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski          .SetCompilationPackage("com.foo")
112dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(&table))
113dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski          .Build();
114dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
115dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<xml::XmlResource> foo_layout = test::BuildXmlDom(R"(
116dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      <View xmlns:android="http://schemas.android.com/apk/res/android">
117dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski        <include layout="@layout/bar" />
118dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      </View>)");
119dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  foo_layout->file.name = test::ParseNameOrDie("com.foo:layout/foo");
120dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
121dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  XmlReferenceLinker xml_linker;
122dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(xml_linker.Consume(context.get(), bar_layout.get()));
123dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(xml_linker.Consume(context.get(), foo_layout.get()));
124dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
125dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  proguard::KeepSet set = proguard::KeepSet(true);
126dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(bar_layout.get(), &set));
127dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(foo_layout.get(), &set));
128dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
129dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::stringstream out;
130dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
131dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
132dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::string actual = out.str();
133dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("ifused class **.R$layout"));
134dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("int foo"));
135dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("int bar"));
136dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
137dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski}
138dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
139dc21dea9b8b1157a4a9347b68301da4307c51168Adam KoskiTEST(ProguardRulesTest, AliasedLayoutRulesAreConditional) {
140dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
141dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
142dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      <View xmlns:android="http://schemas.android.com/apk/res/android">
143dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski        <com.foo.Bar />
144dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      </View>)");
145dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  layout->file.name = test::ParseNameOrDie("layout/foo");
146dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
147dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  proguard::KeepSet set = proguard::KeepSet(true);
148dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  set.AddReference({test::ParseNameOrDie("layout/bar"), {}}, layout->file.name);
149dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
150dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
151dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::stringstream out;
152dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
153dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
154dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::string actual = out.str();
155dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("ifused class **.R$layout"));
156dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("int foo"));
157dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("int bar"));
158dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
159dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski}
160dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
161dc21dea9b8b1157a4a9347b68301da4307c51168Adam KoskiTEST(ProguardRulesTest, NonLayoutReferencesAreUnconditional) {
162dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
163dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
164dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      <View xmlns:android="http://schemas.android.com/apk/res/android">
165dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski        <com.foo.Bar />
166dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski      </View>)");
167dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  layout->file.name = test::ParseNameOrDie("layout/foo");
168dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
169dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  proguard::KeepSet set = proguard::KeepSet(true);
170dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  set.AddReference({test::ParseNameOrDie("style/MyStyle"), {}}, layout->file.name);
171dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
172dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
173dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::stringstream out;
174dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
175dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
176dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  std::string actual = out.str();
177dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  EXPECT_THAT(actual, Not(HasSubstr("ifused")));
178dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski}
179dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski
180f762df257574231ffd08679a69e9cf62fe143dcdAdam LesinskiTEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {
181f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
182f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<xml::XmlResource> layout = test::BuildXmlDom(R"(
183f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
184f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          android:onClick="bar_method" />)");
185f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  layout->file.name = test::ParseNameOrDie("layout/foo");
186f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
187f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  proguard::KeepSet set;
188dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(layout.get(), &set));
189f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
190f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::stringstream out;
191f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
192f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
193f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::string actual = out.str();
194f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("bar_method"));
195f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski}
196f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
197f762df257574231ffd08679a69e9cf62fe143dcdAdam LesinskiTEST(ProguardRulesTest, MenuRulesAreEmitted) {
198f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
199f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::unique_ptr<xml::XmlResource> menu = test::BuildXmlDom(R"(
200f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      <menu xmlns:android="http://schemas.android.com/apk/res/android">
201f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski        <item android:onClick="on_click"
202f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski            android:actionViewClass="com.foo.Bar"
203f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski            android:actionProviderClass="com.foo.Baz"
204f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski            android:name="com.foo.Bat" />
205f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      </menu>)");
206f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  menu->file.name = test::ParseNameOrDie("menu/foo");
207f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
208f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  proguard::KeepSet set;
209dc21dea9b8b1157a4a9347b68301da4307c51168Adam Koski  ASSERT_TRUE(proguard::CollectProguardRules(menu.get(), &set));
210f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
211f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::stringstream out;
212f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
213f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
214f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  std::string actual = out.str();
215f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("on_click"));
216f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
217f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, HasSubstr("com.foo.Baz"));
218f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  EXPECT_THAT(actual, Not(HasSubstr("com.foo.Bat")));
219f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski}
220f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
221f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski}  // namespace aapt
222