1 /*
2 * Copyright (C) 2019 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 "src/profiling/deobfuscator.h"
18
19 #include "test/gtest_and_gmock.h"
20
21 namespace perfetto {
22 namespace profiling {
23
24 bool operator==(const ObfuscatedClass& a, const ObfuscatedClass& b);
operator ==(const ObfuscatedClass & a,const ObfuscatedClass & b)25 bool operator==(const ObfuscatedClass& a, const ObfuscatedClass& b) {
26 return a.deobfuscated_name() == b.deobfuscated_name() &&
27 a.deobfuscated_fields() == b.deobfuscated_fields() &&
28 a.deobfuscated_methods() == b.deobfuscated_methods();
29 }
30
31 namespace {
32
33 using ::testing::_;
34 using ::testing::ElementsAre;
35 using ::testing::Eq;
36 using ::testing::Pair;
37
TEST(ProguardParserTest,ReadClass)38 TEST(ProguardParserTest, ReadClass) {
39 ProguardParser p;
40 ASSERT_TRUE(
41 p.AddLine(
42 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
43 .ok());
44 ASSERT_THAT(p.ConsumeMapping(),
45 ElementsAre(std::pair<std::string, ObfuscatedClass>(
46 "android.arch.a.a.a",
47 "android.arch.core.executor.ArchTaskExecutor")));
48 }
49
TEST(ProguardParserTest,MissingColon)50 TEST(ProguardParserTest, MissingColon) {
51 ProguardParser p;
52 ASSERT_FALSE(
53 p.AddLine(
54 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a")
55 .ok());
56 }
57
TEST(ProguardParserTest,UnexpectedMember)58 TEST(ProguardParserTest, UnexpectedMember) {
59 ProguardParser p;
60 ASSERT_FALSE(
61 p.AddLine(" android.arch.core.executor.TaskExecutor mDelegate -> b")
62 .ok());
63 }
64
TEST(ProguardParserTest,Member)65 TEST(ProguardParserTest, Member) {
66 ProguardParser p;
67 ASSERT_TRUE(
68 p.AddLine(
69 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
70 .ok());
71 ASSERT_TRUE(
72 p.AddLine(" android.arch.core.executor.TaskExecutor mDelegate -> b")
73 .ok());
74 EXPECT_THAT(
75 p.ConsumeMapping(),
76 ElementsAre(std::pair<std::string, ObfuscatedClass>(
77 "android.arch.a.a.a", {"android.arch.core.executor.ArchTaskExecutor",
78 {{"b", "mDelegate"}},
79 {}})));
80 }
81
TEST(ProguardParserTest,Method)82 TEST(ProguardParserTest, Method) {
83 ProguardParser p;
84 ASSERT_TRUE(
85 p.AddLine(
86 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
87 .ok());
88 ASSERT_TRUE(p.AddLine(" 15:15:boolean isMainThread():116:116 -> b").ok());
89 auto mapping = p.ConsumeMapping();
90 ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
91 EXPECT_THAT(
92 mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
93 ElementsAre(Pair(
94 "b", "android.arch.core.executor.ArchTaskExecutor.isMainThread")));
95 }
96
TEST(ProguardParserTest,AmbiguousMethodSameCls)97 TEST(ProguardParserTest, AmbiguousMethodSameCls) {
98 ProguardParser p;
99 ASSERT_TRUE(
100 p.AddLine(
101 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
102 .ok());
103 ASSERT_TRUE(p.AddLine(" 15:15:boolean isMainThread():116:116 -> b").ok());
104 ASSERT_TRUE(
105 p.AddLine(" 15:15:boolean somethingDifferent(int):116:116 -> b").ok());
106 auto mapping = p.ConsumeMapping();
107 ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
108 EXPECT_THAT(
109 mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
110 ElementsAre(Pair(
111 "b", "android.arch.core.executor.ArchTaskExecutor.[ambiguous]")));
112 }
113
TEST(ProguardParserTest,AmbiguousMethodDifferentCls)114 TEST(ProguardParserTest, AmbiguousMethodDifferentCls) {
115 ProguardParser p;
116 ASSERT_TRUE(
117 p.AddLine(
118 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
119 .ok());
120 ASSERT_TRUE(p.AddLine(" 15:15:boolean isMainThread():116:116 -> b").ok());
121 ASSERT_TRUE(
122 p.AddLine(" 15:15:boolean Foo.somethingDifferent(int):116:116 -> b")
123 .ok());
124 auto mapping = p.ConsumeMapping();
125 ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
126 EXPECT_THAT(mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
127 ElementsAre(Pair(
128 "b",
129 "Foo.somethingDifferent | "
130 "android.arch.core.executor.ArchTaskExecutor.isMainThread")));
131 }
132
TEST(ProguardParserTest,AmbiguousMethodSameAndDifferentCls)133 TEST(ProguardParserTest, AmbiguousMethodSameAndDifferentCls) {
134 ProguardParser p;
135 ASSERT_TRUE(
136 p.AddLine(
137 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
138 .ok());
139 ASSERT_TRUE(p.AddLine(" 15:15:boolean isMainThread():116:116 -> b").ok());
140 ASSERT_TRUE(p.AddLine(" 15:15:boolean what(String):116:116 -> b").ok());
141 ASSERT_TRUE(
142 p.AddLine(" 15:15:boolean Foo.somethingDifferent(int):116:116 -> b")
143 .ok());
144 auto mapping = p.ConsumeMapping();
145 ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
146 EXPECT_THAT(mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
147 ElementsAre(Pair(
148 "b",
149 "Foo.somethingDifferent | "
150 "android.arch.core.executor.ArchTaskExecutor.[ambiguous]")));
151 }
152
TEST(ProguardParserTest,AmbiguousMethodSameAndDifferentCls2)153 TEST(ProguardParserTest, AmbiguousMethodSameAndDifferentCls2) {
154 ProguardParser p;
155 ASSERT_TRUE(
156 p.AddLine(
157 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
158 .ok());
159 ASSERT_TRUE(p.AddLine(" 15:15:boolean isMainThread():116:116 -> b").ok());
160 ASSERT_TRUE(p.AddLine(" 15:15:boolean what(String):116:116 -> b").ok());
161 ASSERT_TRUE(
162 p.AddLine(" 15:15:boolean Foo.somethingDifferent(int):116:116 -> b")
163 .ok());
164 ASSERT_TRUE(
165 p.AddLine(" 15:15:boolean Foo.third(int,int):116:116 -> b").ok());
166 auto mapping = p.ConsumeMapping();
167 ASSERT_THAT(mapping, ElementsAre(Pair("android.arch.a.a.a", _)));
168 EXPECT_THAT(mapping.find("android.arch.a.a.a")->second.deobfuscated_methods(),
169 ElementsAre(Pair(
170 "b",
171 "Foo.[ambiguous] | "
172 "android.arch.core.executor.ArchTaskExecutor.[ambiguous]")));
173 }
174
TEST(ProguardParserTest,DuplicateClass)175 TEST(ProguardParserTest, DuplicateClass) {
176 ProguardParser p;
177 ASSERT_TRUE(
178 p.AddLine(
179 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
180 .ok());
181 ASSERT_FALSE(p.AddLine("android.arch.core.executor.ArchTaskExecutor2 -> "
182 "android.arch.a.a.a:")
183 .ok());
184 }
185
TEST(ProguardParserTest,DuplicateField)186 TEST(ProguardParserTest, DuplicateField) {
187 ProguardParser p;
188 ASSERT_TRUE(
189 p.AddLine(
190 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
191 .ok());
192 ASSERT_TRUE(
193 p.AddLine(" android.arch.core.executor.TaskExecutor mDelegate -> b")
194 .ok());
195 ASSERT_FALSE(
196 p.AddLine(" android.arch.core.executor.TaskExecutor mDelegate2 -> b")
197 .ok());
198 }
199
TEST(ProguardParserTest,DuplicateMethod)200 TEST(ProguardParserTest, DuplicateMethod) {
201 ProguardParser p;
202 ASSERT_TRUE(
203 p.AddLine(
204 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
205 .ok());
206 ASSERT_TRUE(p.AddLine(" 15:15:boolean isMainThread():116:116 -> b").ok());
207 ASSERT_TRUE(
208 p.AddLine(" 15:15:boolean doSomething(boolean):116:116 -> b").ok());
209 }
210
TEST(ProguardParserTest,DuplicateFieldSame)211 TEST(ProguardParserTest, DuplicateFieldSame) {
212 ProguardParser p;
213 ASSERT_TRUE(
214 p.AddLine(
215 "android.arch.core.executor.ArchTaskExecutor -> android.arch.a.a.a:")
216 .ok());
217 ASSERT_TRUE(
218 p.AddLine(" android.arch.core.executor.TaskExecutor mDelegate -> b")
219 .ok());
220 ASSERT_TRUE(
221 p.AddLine(
222 " 1:1:android.arch.core.executor.TaskExecutor mDelegate -> b")
223 .ok());
224 }
225
TEST(ProguardParserTest,EmptyLinesAndComments)226 TEST(ProguardParserTest, EmptyLinesAndComments) {
227 ProguardParser p;
228 const char input[] = R"(
229 # comment
230
231 Example$$Class -> C:
232
233 int first -> q
234 # indented comment
235 long second -> o
236 )";
237
238 ASSERT_TRUE(p.AddLines(std::string(input)));
239 EXPECT_THAT(
240 p.ConsumeMapping(),
241 ElementsAre(std::pair<std::string, ObfuscatedClass>(
242 "C", {"Example$$Class", {{"q", "first"}, {"o", "second"}}, {}})));
243 }
244
245 } // namespace
246 } // namespace profiling
247 } // namespace perfetto
248