xref: /aosp_15_r20/system/extras/simpleperf/report_utils_test.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
20*288bf522SAndroid Build Coastguard Worker 
21*288bf522SAndroid Build Coastguard Worker #include <string>
22*288bf522SAndroid Build Coastguard Worker #include <vector>
23*288bf522SAndroid Build Coastguard Worker 
24*288bf522SAndroid Build Coastguard Worker #include "record_file.h"
25*288bf522SAndroid Build Coastguard Worker #include "report_utils.h"
26*288bf522SAndroid Build Coastguard Worker #include "thread_tree.h"
27*288bf522SAndroid Build Coastguard Worker 
28*288bf522SAndroid Build Coastguard Worker using namespace simpleperf;
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST(ProguardMappingRetrace,smoke)31*288bf522SAndroid Build Coastguard Worker TEST(ProguardMappingRetrace, smoke) {
32*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
33*288bf522SAndroid Build Coastguard Worker   close(tmpfile.release());
34*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(
35*288bf522SAndroid Build Coastguard Worker       android::base::WriteStringToFile("original.class.A -> A:\n"
36*288bf522SAndroid Build Coastguard Worker                                        "\n"
37*288bf522SAndroid Build Coastguard Worker                                        "    void method_a() -> a\n"
38*288bf522SAndroid Build Coastguard Worker                                        "    void method_b() -> b\n"
39*288bf522SAndroid Build Coastguard Worker                                        "      # {\"id\":\"com.android.tools.r8.synthesized\"}\n"
40*288bf522SAndroid Build Coastguard Worker                                        "      # some other comments\n"
41*288bf522SAndroid Build Coastguard Worker                                        "    void original.class.M.method_c() -> c\n"
42*288bf522SAndroid Build Coastguard Worker                                        "    void original.class.A.method_d() -> d\n"
43*288bf522SAndroid Build Coastguard Worker                                        "original.class.B -> B:\n"
44*288bf522SAndroid Build Coastguard Worker                                        "# some other comments\n"
45*288bf522SAndroid Build Coastguard Worker                                        "original.class.C -> C:\n"
46*288bf522SAndroid Build Coastguard Worker                                        "# {\'id\':\'com.android.tools.r8.synthesized\'}\n",
47*288bf522SAndroid Build Coastguard Worker                                        tmpfile.path));
48*288bf522SAndroid Build Coastguard Worker   ProguardMappingRetrace retrace;
49*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.AddProguardMappingFile(tmpfile.path));
50*288bf522SAndroid Build Coastguard Worker   std::string original_name;
51*288bf522SAndroid Build Coastguard Worker   bool synthesized;
52*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.DeObfuscateJavaMethods("A.a", &original_name, &synthesized));
53*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(original_name, "original.class.A.method_a");
54*288bf522SAndroid Build Coastguard Worker   ASSERT_FALSE(synthesized);
55*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.DeObfuscateJavaMethods("A.b", &original_name, &synthesized));
56*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(original_name, "original.class.A.method_b");
57*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(synthesized);
58*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.DeObfuscateJavaMethods("A.c", &original_name, &synthesized));
59*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(original_name, "original.class.M.method_c");
60*288bf522SAndroid Build Coastguard Worker   ASSERT_FALSE(synthesized);
61*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.DeObfuscateJavaMethods("A.d", &original_name, &synthesized));
62*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(original_name, "original.class.A.method_d");
63*288bf522SAndroid Build Coastguard Worker   ASSERT_FALSE(synthesized);
64*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.DeObfuscateJavaMethods("B.b", &original_name, &synthesized));
65*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(original_name, "original.class.B.b");
66*288bf522SAndroid Build Coastguard Worker   ASSERT_FALSE(synthesized);
67*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(retrace.DeObfuscateJavaMethods("C.c", &original_name, &synthesized));
68*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(original_name, "original.class.C.c");
69*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(synthesized);
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker 
72*288bf522SAndroid Build Coastguard Worker class CallChainReportBuilderTest : public testing::Test {
73*288bf522SAndroid Build Coastguard Worker  protected:
SetUp()74*288bf522SAndroid Build Coastguard Worker   virtual void SetUp() {
75*288bf522SAndroid Build Coastguard Worker     // To test different options for CallChainReportBuilder, we create a fake thread, add fake
76*288bf522SAndroid Build Coastguard Worker     // libraries used by the thread, and provide fake symbols in each library. We need four
77*288bf522SAndroid Build Coastguard Worker     // types of libraries: native, interpreter, jit cache and dex file.
78*288bf522SAndroid Build Coastguard Worker     thread_tree.SetThreadName(1, 1, "thread1");
79*288bf522SAndroid Build Coastguard Worker     thread = thread_tree.FindThread(1);
80*288bf522SAndroid Build Coastguard Worker 
81*288bf522SAndroid Build Coastguard Worker     // Add symbol info for the native library.
82*288bf522SAndroid Build Coastguard Worker     SetSymbols(fake_native_lib_path, DSO_ELF_FILE,
83*288bf522SAndroid Build Coastguard Worker                {
84*288bf522SAndroid Build Coastguard Worker                    Symbol("native_func1", 0x0, 0x100),
85*288bf522SAndroid Build Coastguard Worker                    Symbol("art_jni_trampoline", 0x100, 0x100),
86*288bf522SAndroid Build Coastguard Worker                });
87*288bf522SAndroid Build Coastguard Worker 
88*288bf522SAndroid Build Coastguard Worker     // Add symbol info for the interpreter library.
89*288bf522SAndroid Build Coastguard Worker     SetSymbols(
90*288bf522SAndroid Build Coastguard Worker         fake_interpreter_path, DSO_ELF_FILE,
91*288bf522SAndroid Build Coastguard Worker         {
92*288bf522SAndroid Build Coastguard Worker             Symbol("art_func1", 0x0, 0x100),
93*288bf522SAndroid Build Coastguard Worker             Symbol("art_func2", 0x100, 0x100),
94*288bf522SAndroid Build Coastguard Worker             Symbol("_ZN3artL13Method_invokeEP7_JNIEnvP8_jobjectS3_P13_jobjectArray", 0x200, 0x100),
95*288bf522SAndroid Build Coastguard Worker             Symbol("art_quick_generic_jni_trampoline", 0x300, 0x100),
96*288bf522SAndroid Build Coastguard Worker         });
97*288bf522SAndroid Build Coastguard Worker 
98*288bf522SAndroid Build Coastguard Worker     // Add symbol info for the dex file.
99*288bf522SAndroid Build Coastguard Worker     SetSymbols(fake_dex_file_path, DSO_DEX_FILE,
100*288bf522SAndroid Build Coastguard Worker                {
101*288bf522SAndroid Build Coastguard Worker                    Symbol("java_method1", 0x0, 0x100),
102*288bf522SAndroid Build Coastguard Worker                    Symbol("java_method2", 0x100, 0x100),
103*288bf522SAndroid Build Coastguard Worker                    Symbol("obfuscated_class.obfuscated_java_method", 0x200, 0x100),
104*288bf522SAndroid Build Coastguard Worker                });
105*288bf522SAndroid Build Coastguard Worker 
106*288bf522SAndroid Build Coastguard Worker     // Add symbol info for the jit cache.
107*288bf522SAndroid Build Coastguard Worker     SetSymbols(fake_jit_cache_path, DSO_ELF_FILE,
108*288bf522SAndroid Build Coastguard Worker                {
109*288bf522SAndroid Build Coastguard Worker                    Symbol("java_method2", 0x3000, 0x100),
110*288bf522SAndroid Build Coastguard Worker                    Symbol("java_method3", 0x3100, 0x100),
111*288bf522SAndroid Build Coastguard Worker                    Symbol("obfuscated_class.obfuscated_java_method2", 0x3200, 0x100),
112*288bf522SAndroid Build Coastguard Worker                    Symbol("obfuscated_class.java_method4", 0x3300, 0x100),
113*288bf522SAndroid Build Coastguard Worker                });
114*288bf522SAndroid Build Coastguard Worker 
115*288bf522SAndroid Build Coastguard Worker     // Add map layout for libraries used in the thread:
116*288bf522SAndroid Build Coastguard Worker     // 0x0000 - 0x1000 is mapped to the native library.
117*288bf522SAndroid Build Coastguard Worker     // 0x1000 - 0x2000 is mapped to the interpreter library.
118*288bf522SAndroid Build Coastguard Worker     // 0x2000 - 0x3000 is mapped to the dex file.
119*288bf522SAndroid Build Coastguard Worker     // 0x3000 - 0x4000 is mapped to the jit cache.
120*288bf522SAndroid Build Coastguard Worker     thread_tree.AddThreadMap(1, 1, 0x0, 0x1000, 0x0, fake_native_lib_path);
121*288bf522SAndroid Build Coastguard Worker     thread_tree.AddThreadMap(1, 1, 0x1000, 0x1000, 0x0, fake_interpreter_path);
122*288bf522SAndroid Build Coastguard Worker     thread_tree.AddThreadMap(1, 1, 0x2000, 0x1000, 0x0, fake_dex_file_path);
123*288bf522SAndroid Build Coastguard Worker     thread_tree.AddThreadMap(1, 1, 0x3000, 0x1000, 0x0, fake_jit_cache_path,
124*288bf522SAndroid Build Coastguard Worker                              map_flags::PROT_JIT_SYMFILE_MAP);
125*288bf522SAndroid Build Coastguard Worker   }
126*288bf522SAndroid Build Coastguard Worker 
SetSymbols(const std::string & path,DsoType dso_type,const std::vector<Symbol> & symbols)127*288bf522SAndroid Build Coastguard Worker   void SetSymbols(const std::string& path, DsoType dso_type, const std::vector<Symbol>& symbols) {
128*288bf522SAndroid Build Coastguard Worker     FileFeature file;
129*288bf522SAndroid Build Coastguard Worker     file.path = path;
130*288bf522SAndroid Build Coastguard Worker     file.type = dso_type;
131*288bf522SAndroid Build Coastguard Worker     file.min_vaddr = file.file_offset_of_min_vaddr = 0;
132*288bf522SAndroid Build Coastguard Worker     file.symbols = symbols;
133*288bf522SAndroid Build Coastguard Worker     thread_tree.AddDsoInfo(file);
134*288bf522SAndroid Build Coastguard Worker   }
135*288bf522SAndroid Build Coastguard Worker 
136*288bf522SAndroid Build Coastguard Worker   ThreadTree thread_tree;
137*288bf522SAndroid Build Coastguard Worker   const ThreadEntry* thread;
138*288bf522SAndroid Build Coastguard Worker   const std::string fake_native_lib_path = "fake_dir/fake_native_lib.so";
139*288bf522SAndroid Build Coastguard Worker   const std::string fake_interpreter_path = "fake_dir/libart.so";
140*288bf522SAndroid Build Coastguard Worker   const std::string fake_dex_file_path = "fake_dir/framework.jar";
141*288bf522SAndroid Build Coastguard Worker   const std::string fake_jit_cache_path = "fake_jit_app_cache:0";
142*288bf522SAndroid Build Coastguard Worker 
143*288bf522SAndroid Build Coastguard Worker   const std::vector<uint64_t> fake_ips = {
144*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
145*288bf522SAndroid Build Coastguard Worker       0x1100,  // art_func2
146*288bf522SAndroid Build Coastguard Worker       0x2000,  // java_method1 in dex file
147*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
148*288bf522SAndroid Build Coastguard Worker       0x1100,  // art_func2
149*288bf522SAndroid Build Coastguard Worker       0x3000,  // java_method2 in jit cache
150*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
151*288bf522SAndroid Build Coastguard Worker       0x1100,  // art_func2
152*288bf522SAndroid Build Coastguard Worker   };
153*288bf522SAndroid Build Coastguard Worker };
154*288bf522SAndroid Build Coastguard Worker 
155*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,default_option)156*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, default_option) {
157*288bf522SAndroid Build Coastguard Worker   // Test default option: remove_art_frame = true, convert_jit_frame = true.
158*288bf522SAndroid Build Coastguard Worker   // The callchain shouldn't include interpreter frames. And the JIT frame is
159*288bf522SAndroid Build Coastguard Worker   // converted to a dex frame.
160*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
161*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
162*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2);
163*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2000);
164*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->Name(), "java_method1");
165*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
166*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0);
167*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
168*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3000);
169*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->Name(), "java_method2");
170*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_dex_file_path);
171*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x100);
172*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
173*288bf522SAndroid Build Coastguard Worker }
174*288bf522SAndroid Build Coastguard Worker 
175*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,not_convert_jit_frame)176*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, not_convert_jit_frame) {
177*288bf522SAndroid Build Coastguard Worker   // Test option: remove_art_frame = true, convert_jit_frame = false.
178*288bf522SAndroid Build Coastguard Worker   // The callchain shouldn't include interpreter frames. And the JIT frame isn't
179*288bf522SAndroid Build Coastguard Worker   // converted to a dex frame.
180*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
181*288bf522SAndroid Build Coastguard Worker   builder.SetConvertJITFrame(false);
182*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
183*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2);
184*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2000);
185*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->Name(), "java_method1");
186*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
187*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0);
188*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
189*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3000);
190*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->Name(), "java_method2");
191*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_jit_cache_path);
192*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x3000);
193*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
194*288bf522SAndroid Build Coastguard Worker }
195*288bf522SAndroid Build Coastguard Worker 
196*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,not_remove_art_frame)197*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, not_remove_art_frame) {
198*288bf522SAndroid Build Coastguard Worker   // Test option: remove_art_frame = false, convert_jit_frame = true.
199*288bf522SAndroid Build Coastguard Worker   // The callchain should include interpreter frames. And the JIT frame is
200*288bf522SAndroid Build Coastguard Worker   // converted to a dex frame.
201*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
202*288bf522SAndroid Build Coastguard Worker   builder.SetRemoveArtFrame(false);
203*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
204*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 8);
205*288bf522SAndroid Build Coastguard Worker   for (size_t i : {0, 3, 6}) {
206*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].ip, 0x1000);
207*288bf522SAndroid Build Coastguard Worker     ASSERT_STREQ(entries[i].symbol->Name(), "art_func1");
208*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].dso->Path(), fake_interpreter_path);
209*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].vaddr_in_file, 0);
210*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].execution_type, CallChainExecutionType::ART_METHOD);
211*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i + 1].ip, 0x1100);
212*288bf522SAndroid Build Coastguard Worker     ASSERT_STREQ(entries[i + 1].symbol->Name(), "art_func2");
213*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i + 1].dso->Path(), fake_interpreter_path);
214*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i + 1].vaddr_in_file, 0x100);
215*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i + 1].execution_type, CallChainExecutionType::ART_METHOD);
216*288bf522SAndroid Build Coastguard Worker   }
217*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].ip, 0x2000);
218*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[2].symbol->Name(), "java_method1");
219*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].dso->Path(), fake_dex_file_path);
220*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].vaddr_in_file, 0);
221*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
222*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[5].ip, 0x3000);
223*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[5].symbol->Name(), "java_method2");
224*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[5].dso->Path(), fake_dex_file_path);
225*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[5].vaddr_in_file, 0x100);
226*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[5].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
227*288bf522SAndroid Build Coastguard Worker }
228*288bf522SAndroid Build Coastguard Worker 
229*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,remove_jit_frame_called_by_dex_frame)230*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, remove_jit_frame_called_by_dex_frame) {
231*288bf522SAndroid Build Coastguard Worker   // Test option: remove_art_frame = true, convert_jit_frame = true.
232*288bf522SAndroid Build Coastguard Worker   // The callchain should remove the JIT frame called by a dex frame having the same symbol name.
233*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
234*288bf522SAndroid Build Coastguard Worker       0x3000,  // java_method2 in jit cache
235*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
236*288bf522SAndroid Build Coastguard Worker       0x1100,  // art_func2
237*288bf522SAndroid Build Coastguard Worker       0x2100,  // java_method2 in dex file
238*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
239*288bf522SAndroid Build Coastguard Worker   };
240*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
241*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
242*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 1);
243*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2100);
244*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->Name(), "java_method2");
245*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
246*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x100);
247*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
248*288bf522SAndroid Build Coastguard Worker }
249*288bf522SAndroid Build Coastguard Worker 
250*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,remove_art_frame_only_near_jvm_method)251*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, remove_art_frame_only_near_jvm_method) {
252*288bf522SAndroid Build Coastguard Worker   // Test option: remove_art_frame = true, convert_jit_frame = true.
253*288bf522SAndroid Build Coastguard Worker   // The callchain should not remove ART symbols not near a JVM method.
254*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
255*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
256*288bf522SAndroid Build Coastguard Worker       0x0,     // native_func1
257*288bf522SAndroid Build Coastguard Worker       0x2000,  // java_method1 in dex file
258*288bf522SAndroid Build Coastguard Worker       0x0,     // native_func1
259*288bf522SAndroid Build Coastguard Worker       0x1000,  // art_func1
260*288bf522SAndroid Build Coastguard Worker   };
261*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
262*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
263*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 5);
264*288bf522SAndroid Build Coastguard Worker   for (size_t i : {0, 4}) {
265*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].ip, 0x1000);
266*288bf522SAndroid Build Coastguard Worker     ASSERT_STREQ(entries[i].symbol->Name(), "art_func1");
267*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].dso->Path(), fake_interpreter_path);
268*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].vaddr_in_file, 0);
269*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].execution_type, CallChainExecutionType::NATIVE_METHOD);
270*288bf522SAndroid Build Coastguard Worker   }
271*288bf522SAndroid Build Coastguard Worker   for (size_t i : {1, 3}) {
272*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].ip, 0x0);
273*288bf522SAndroid Build Coastguard Worker     ASSERT_STREQ(entries[i].symbol->Name(), "native_func1");
274*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].dso->Path(), fake_native_lib_path);
275*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].vaddr_in_file, 0);
276*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].execution_type, CallChainExecutionType::NATIVE_METHOD);
277*288bf522SAndroid Build Coastguard Worker   }
278*288bf522SAndroid Build Coastguard Worker 
279*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].ip, 0x2000);
280*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[2].symbol->Name(), "java_method1");
281*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].dso->Path(), fake_dex_file_path);
282*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].vaddr_in_file, 0x0);
283*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
284*288bf522SAndroid Build Coastguard Worker }
285*288bf522SAndroid Build Coastguard Worker 
286*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,keep_art_jni_method)287*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, keep_art_jni_method) {
288*288bf522SAndroid Build Coastguard Worker   // Test option: remove_art_frame = true.
289*288bf522SAndroid Build Coastguard Worker   // The callchain should remove art_jni_trampoline, but keep jni methods.
290*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
291*288bf522SAndroid Build Coastguard Worker       0x1200,  // art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)
292*288bf522SAndroid Build Coastguard Worker       0x100,   // art_jni_trampoline
293*288bf522SAndroid Build Coastguard Worker       0x2000,  // java_method1 in dex file
294*288bf522SAndroid Build Coastguard Worker       0x1200,  // art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)
295*288bf522SAndroid Build Coastguard Worker       0x1300,  // art_quick_generic_jni_trampoline
296*288bf522SAndroid Build Coastguard Worker   };
297*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
298*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
299*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 3);
300*288bf522SAndroid Build Coastguard Worker   for (size_t i : {0, 2}) {
301*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].ip, 0x1200);
302*288bf522SAndroid Build Coastguard Worker     ASSERT_STREQ(entries[i].symbol->DemangledName(),
303*288bf522SAndroid Build Coastguard Worker                  "art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)");
304*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].dso->Path(), fake_interpreter_path);
305*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].vaddr_in_file, 0x200);
306*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[i].execution_type, CallChainExecutionType::NATIVE_METHOD);
307*288bf522SAndroid Build Coastguard Worker   }
308*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x2000);
309*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->Name(), "java_method1");
310*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_dex_file_path);
311*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x0);
312*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
313*288bf522SAndroid Build Coastguard Worker }
314*288bf522SAndroid Build Coastguard Worker 
315*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,add_proguard_mapping_file)316*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, add_proguard_mapping_file) {
317*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
318*288bf522SAndroid Build Coastguard Worker       0x2200,  // 2200,  // obfuscated_class.obfuscated_java_method
319*288bf522SAndroid Build Coastguard Worker       0x3200,  // 3200,  // obfuscated_class.obfuscated_java_method2
320*288bf522SAndroid Build Coastguard Worker       0x3300,  // 3300,  // obfuscated_class.java_method4
321*288bf522SAndroid Build Coastguard Worker   };
322*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
323*288bf522SAndroid Build Coastguard Worker   // Symbol names aren't changed when not given proguard mapping files.
324*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
325*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 3);
326*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2200);
327*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(), "obfuscated_class.obfuscated_java_method");
328*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
329*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x200);
330*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
331*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3200);
332*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->DemangledName(), "obfuscated_class.obfuscated_java_method2");
333*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_jit_cache_path);
334*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x3200);
335*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
336*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].ip, 0x3300);
337*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[2].symbol->DemangledName(), "obfuscated_class.java_method4");
338*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].dso->Path(), fake_jit_cache_path);
339*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].vaddr_in_file, 0x3300);
340*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
341*288bf522SAndroid Build Coastguard Worker 
342*288bf522SAndroid Build Coastguard Worker   // Symbol names are changed when given a proguard mapping file.
343*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
344*288bf522SAndroid Build Coastguard Worker   close(tmpfile.release());
345*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(
346*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer -> obfuscated_class:\n"
347*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat read(androidx.versionedparcelable.Versioned"
348*288bf522SAndroid Build Coastguard Worker       "Parcel) -> obfuscated_java_method\n"
349*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat "
350*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer.read2(androidx.versionedparcelable."
351*288bf522SAndroid Build Coastguard Worker       "VersionedParcel) -> obfuscated_java_method2",
352*288bf522SAndroid Build Coastguard Worker       tmpfile.path));
353*288bf522SAndroid Build Coastguard Worker   builder.AddProguardMappingFile(tmpfile.path);
354*288bf522SAndroid Build Coastguard Worker   entries = builder.Build(thread, fake_ips, 0);
355*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 3);
356*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2200);
357*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(),
358*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read");
359*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
360*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x200);
361*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
362*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3200);
363*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->DemangledName(),
364*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read2");
365*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_jit_cache_path);
366*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x3200);
367*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
368*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[2].symbol->DemangledName(),
369*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.java_method4");
370*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].dso->Path(), fake_jit_cache_path);
371*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].vaddr_in_file, 0x3300);
372*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[2].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
373*288bf522SAndroid Build Coastguard Worker }
374*288bf522SAndroid Build Coastguard Worker 
375*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,not_remove_synthesized_frame_by_default)376*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, not_remove_synthesized_frame_by_default) {
377*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
378*288bf522SAndroid Build Coastguard Worker       0x2200,  // 2200,  // obfuscated_class.obfuscated_java_method
379*288bf522SAndroid Build Coastguard Worker       0x3200,  // 3200,  // obfuscated_class.obfuscated_java_method2
380*288bf522SAndroid Build Coastguard Worker   };
381*288bf522SAndroid Build Coastguard Worker 
382*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
383*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(
384*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer -> obfuscated_class:\n"
385*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat read(androidx.versionedparcelable.Versioned"
386*288bf522SAndroid Build Coastguard Worker       "Parcel) -> obfuscated_java_method\n"
387*288bf522SAndroid Build Coastguard Worker       "      # {\"id\":\"com.android.tools.r8.synthesized\"}\n"
388*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat "
389*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer.read2(androidx.versionedparcelable."
390*288bf522SAndroid Build Coastguard Worker       "VersionedParcel) -> obfuscated_java_method2",
391*288bf522SAndroid Build Coastguard Worker       tmpfile.path));
392*288bf522SAndroid Build Coastguard Worker 
393*288bf522SAndroid Build Coastguard Worker   // By default, synthesized frames are kept.
394*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
395*288bf522SAndroid Build Coastguard Worker   builder.AddProguardMappingFile(tmpfile.path);
396*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
397*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2);
398*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2200);
399*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(),
400*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read");
401*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
402*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x200);
403*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
404*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3200);
405*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->DemangledName(),
406*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read2");
407*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_jit_cache_path);
408*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x3200);
409*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
410*288bf522SAndroid Build Coastguard Worker }
411*288bf522SAndroid Build Coastguard Worker 
412*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,remove_synthesized_frame_with_env_variable)413*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, remove_synthesized_frame_with_env_variable) {
414*288bf522SAndroid Build Coastguard Worker   // Windows doesn't support setenv and unsetenv. So don't test on it.
415*288bf522SAndroid Build Coastguard Worker #if !defined(__WIN32)
416*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
417*288bf522SAndroid Build Coastguard Worker       0x2200,  // 2200,  // obfuscated_class.obfuscated_java_method
418*288bf522SAndroid Build Coastguard Worker       0x3200,  // 3200,  // obfuscated_class.obfuscated_java_method2
419*288bf522SAndroid Build Coastguard Worker   };
420*288bf522SAndroid Build Coastguard Worker 
421*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
422*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(
423*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer -> obfuscated_class:\n"
424*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat read(androidx.versionedparcelable.Versioned"
425*288bf522SAndroid Build Coastguard Worker       "Parcel) -> obfuscated_java_method\n"
426*288bf522SAndroid Build Coastguard Worker       "      # {\"id\":\"com.android.tools.r8.synthesized\"}\n"
427*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat "
428*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer.read2(androidx.versionedparcelable."
429*288bf522SAndroid Build Coastguard Worker       "VersionedParcel) -> obfuscated_java_method2",
430*288bf522SAndroid Build Coastguard Worker       tmpfile.path));
431*288bf522SAndroid Build Coastguard Worker 
432*288bf522SAndroid Build Coastguard Worker   // With environment variable set, synthesized frames are removed.
433*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(setenv("REMOVE_R8_SYNTHESIZED_FRAME", "1", 1), 0);
434*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
435*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(unsetenv("REMOVE_R8_SYNTHESIZED_FRAME"), 0);
436*288bf522SAndroid Build Coastguard Worker   builder.AddProguardMappingFile(tmpfile.path);
437*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
438*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 1);
439*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x3200);
440*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(),
441*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read2");
442*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_jit_cache_path);
443*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x3200);
444*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
445*288bf522SAndroid Build Coastguard Worker #endif  // !defined(__WIN32)
446*288bf522SAndroid Build Coastguard Worker }
447*288bf522SAndroid Build Coastguard Worker 
448*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,add_proguard_mapping_file_for_jit_method_with_signature)449*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, add_proguard_mapping_file_for_jit_method_with_signature) {
450*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
451*288bf522SAndroid Build Coastguard Worker       0x3200,  // 3200,  // void ctep.v(cteo, ctgc, ctbn)
452*288bf522SAndroid Build Coastguard Worker   };
453*288bf522SAndroid Build Coastguard Worker   SetSymbols(fake_jit_cache_path, DSO_ELF_FILE,
454*288bf522SAndroid Build Coastguard Worker              {Symbol("void ctep.v(cteo, ctgc, ctbn)", 0x3200, 0x100)});
455*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
456*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
457*288bf522SAndroid Build Coastguard Worker   close(tmpfile.release());
458*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(
459*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer -> ctep:\n"
460*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat read(androidx.versionedparcelable.Versioned"
461*288bf522SAndroid Build Coastguard Worker       "Parcel) -> v\n",
462*288bf522SAndroid Build Coastguard Worker       tmpfile.path));
463*288bf522SAndroid Build Coastguard Worker   builder.AddProguardMappingFile(tmpfile.path);
464*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
465*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 1);
466*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x3200);
467*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(),
468*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read");
469*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_jit_cache_path);
470*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x3200);
471*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
472*288bf522SAndroid Build Coastguard Worker }
473*288bf522SAndroid Build Coastguard Worker 
474*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,add_proguard_mapping_file_for_compiled_java_method_with_signature)475*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest,
476*288bf522SAndroid Build Coastguard Worker        add_proguard_mapping_file_for_compiled_java_method_with_signature) {
477*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
478*288bf522SAndroid Build Coastguard Worker   close(tmpfile.release());
479*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(
480*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer -> ctep:\n"
481*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat read(androidx.versionedparcelable.Versioned"
482*288bf522SAndroid Build Coastguard Worker       "Parcel) -> v\n",
483*288bf522SAndroid Build Coastguard Worker       tmpfile.path));
484*288bf522SAndroid Build Coastguard Worker 
485*288bf522SAndroid Build Coastguard Worker   for (const char* suffix : {".odex", ".oat", ".dex"}) {
486*288bf522SAndroid Build Coastguard Worker     std::string compiled_java_path = "compiled_java" + std::string(suffix);
487*288bf522SAndroid Build Coastguard Worker     SetSymbols(compiled_java_path, DSO_ELF_FILE,
488*288bf522SAndroid Build Coastguard Worker                {Symbol("void ctep.v(cteo, ctgc, ctbn)", 0x0, 0x100)});
489*288bf522SAndroid Build Coastguard Worker     thread_tree.AddThreadMap(1, 1, 0x4000, 0x1000, 0x0, compiled_java_path);
490*288bf522SAndroid Build Coastguard Worker     std::vector<uint64_t> fake_ips = {
491*288bf522SAndroid Build Coastguard Worker         0x4000,  // 4000,  // void ctep.v(cteo, ctgc, ctbn)
492*288bf522SAndroid Build Coastguard Worker     };
493*288bf522SAndroid Build Coastguard Worker 
494*288bf522SAndroid Build Coastguard Worker     CallChainReportBuilder builder(thread_tree);
495*288bf522SAndroid Build Coastguard Worker     builder.AddProguardMappingFile(tmpfile.path);
496*288bf522SAndroid Build Coastguard Worker     std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
497*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries.size(), 1);
498*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[0].ip, 0x4000);
499*288bf522SAndroid Build Coastguard Worker     ASSERT_STREQ(entries[0].symbol->DemangledName(),
500*288bf522SAndroid Build Coastguard Worker                  "android.support.v4.app.RemoteActionCompatParcelizer.read");
501*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[0].dso->Path(), compiled_java_path);
502*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[0].vaddr_in_file, 0x0);
503*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::NATIVE_METHOD);
504*288bf522SAndroid Build Coastguard Worker   }
505*288bf522SAndroid Build Coastguard Worker }
506*288bf522SAndroid Build Coastguard Worker 
507*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,convert_jit_frame_for_jit_method_with_signature)508*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, convert_jit_frame_for_jit_method_with_signature) {
509*288bf522SAndroid Build Coastguard Worker   std::vector<uint64_t> fake_ips = {
510*288bf522SAndroid Build Coastguard Worker       0x2200,  // 2200,  // ctep.v
511*288bf522SAndroid Build Coastguard Worker       0x3200,  // 3200,  // void ctep.v(cteo, ctgc, ctbn)
512*288bf522SAndroid Build Coastguard Worker   };
513*288bf522SAndroid Build Coastguard Worker   SetSymbols(fake_dex_file_path, DSO_DEX_FILE, {Symbol("ctep.v", 0x200, 0x100)});
514*288bf522SAndroid Build Coastguard Worker   SetSymbols(fake_jit_cache_path, DSO_ELF_FILE,
515*288bf522SAndroid Build Coastguard Worker              {Symbol("void ctep.v(cteo, ctgc, ctbn)", 0x3200, 0x100)});
516*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
517*288bf522SAndroid Build Coastguard Worker   // Test if we can convert jit method with signature.
518*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
519*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2);
520*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2200);
521*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(), "ctep.v");
522*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
523*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x200);
524*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
525*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3200);
526*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->DemangledName(), "ctep.v");
527*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_dex_file_path);
528*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x200);
529*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
530*288bf522SAndroid Build Coastguard Worker 
531*288bf522SAndroid Build Coastguard Worker   // Test adding proguard mapping file.
532*288bf522SAndroid Build Coastguard Worker   TemporaryFile tmpfile;
533*288bf522SAndroid Build Coastguard Worker   close(tmpfile.release());
534*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(
535*288bf522SAndroid Build Coastguard Worker       "android.support.v4.app.RemoteActionCompatParcelizer -> ctep:\n"
536*288bf522SAndroid Build Coastguard Worker       "    13:13:androidx.core.app.RemoteActionCompat read(androidx.versionedparcelable.Versioned"
537*288bf522SAndroid Build Coastguard Worker       "Parcel) -> v\n",
538*288bf522SAndroid Build Coastguard Worker       tmpfile.path));
539*288bf522SAndroid Build Coastguard Worker   builder.AddProguardMappingFile(tmpfile.path);
540*288bf522SAndroid Build Coastguard Worker   entries = builder.Build(thread, fake_ips, 0);
541*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2);
542*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2200);
543*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->DemangledName(),
544*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read");
545*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
546*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0x200);
547*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
548*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3200);
549*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->DemangledName(),
550*288bf522SAndroid Build Coastguard Worker                "android.support.v4.app.RemoteActionCompatParcelizer.read");
551*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_dex_file_path);
552*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x200);
553*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
554*288bf522SAndroid Build Coastguard Worker }
555*288bf522SAndroid Build Coastguard Worker 
556*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(CallChainReportBuilderTest,remove_method_name)557*288bf522SAndroid Build Coastguard Worker TEST_F(CallChainReportBuilderTest, remove_method_name) {
558*288bf522SAndroid Build Coastguard Worker   // Test excluding method names.
559*288bf522SAndroid Build Coastguard Worker   CallChainReportBuilder builder(thread_tree);
560*288bf522SAndroid Build Coastguard Worker   builder.SetRemoveArtFrame(false);
561*288bf522SAndroid Build Coastguard Worker   builder.RemoveMethod("art_");
562*288bf522SAndroid Build Coastguard Worker   std::vector<CallChainReportEntry> entries = builder.Build(thread, fake_ips, 0);
563*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 2);
564*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2000);
565*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->Name(), "java_method1");
566*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
567*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0);
568*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
569*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].ip, 0x3000);
570*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[1].symbol->Name(), "java_method2");
571*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].dso->Path(), fake_dex_file_path);
572*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].vaddr_in_file, 0x100);
573*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[1].execution_type, CallChainExecutionType::JIT_JVM_METHOD);
574*288bf522SAndroid Build Coastguard Worker 
575*288bf522SAndroid Build Coastguard Worker   builder.RemoveMethod("java_method2");
576*288bf522SAndroid Build Coastguard Worker   entries = builder.Build(thread, fake_ips, 0);
577*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 1);
578*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].ip, 0x2000);
579*288bf522SAndroid Build Coastguard Worker   ASSERT_STREQ(entries[0].symbol->Name(), "java_method1");
580*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].dso->Path(), fake_dex_file_path);
581*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].vaddr_in_file, 0);
582*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries[0].execution_type, CallChainExecutionType::INTERPRETED_JVM_METHOD);
583*288bf522SAndroid Build Coastguard Worker 
584*288bf522SAndroid Build Coastguard Worker   builder.RemoveMethod("java_method1");
585*288bf522SAndroid Build Coastguard Worker   entries = builder.Build(thread, fake_ips, 0);
586*288bf522SAndroid Build Coastguard Worker   ASSERT_EQ(entries.size(), 0);
587*288bf522SAndroid Build Coastguard Worker }
588*288bf522SAndroid Build Coastguard Worker 
589*288bf522SAndroid Build Coastguard Worker class ThreadReportBuilderTest : public testing::Test {
590*288bf522SAndroid Build Coastguard Worker  protected:
SetUp()591*288bf522SAndroid Build Coastguard Worker   virtual void SetUp() {
592*288bf522SAndroid Build Coastguard Worker     thread_tree.SetThreadName(1, 1, "thread1");
593*288bf522SAndroid Build Coastguard Worker     thread_tree.SetThreadName(1, 2, "thread-pool1");
594*288bf522SAndroid Build Coastguard Worker     thread_tree.SetThreadName(1, 3, "thread-pool2");
595*288bf522SAndroid Build Coastguard Worker   }
596*288bf522SAndroid Build Coastguard Worker 
IsReportEqual(const ThreadReport & report1,const ThreadReport & report2)597*288bf522SAndroid Build Coastguard Worker   bool IsReportEqual(const ThreadReport& report1, const ThreadReport& report2) {
598*288bf522SAndroid Build Coastguard Worker     return report1.pid == report2.pid && report1.tid == report2.tid &&
599*288bf522SAndroid Build Coastguard Worker            strcmp(report1.thread_name, report2.thread_name) == 0;
600*288bf522SAndroid Build Coastguard Worker   }
601*288bf522SAndroid Build Coastguard Worker 
602*288bf522SAndroid Build Coastguard Worker   ThreadTree thread_tree;
603*288bf522SAndroid Build Coastguard Worker };
604*288bf522SAndroid Build Coastguard Worker 
605*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(ThreadReportBuilderTest,no_setting)606*288bf522SAndroid Build Coastguard Worker TEST_F(ThreadReportBuilderTest, no_setting) {
607*288bf522SAndroid Build Coastguard Worker   ThreadReportBuilder builder;
608*288bf522SAndroid Build Coastguard Worker   ThreadEntry* thread = thread_tree.FindThread(1);
609*288bf522SAndroid Build Coastguard Worker   ThreadReport report = builder.Build(*thread);
610*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(IsReportEqual(report, ThreadReport(1, 1, "thread1")));
611*288bf522SAndroid Build Coastguard Worker }
612*288bf522SAndroid Build Coastguard Worker 
613*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(ThreadReportBuilderTest,aggregate_threads)614*288bf522SAndroid Build Coastguard Worker TEST_F(ThreadReportBuilderTest, aggregate_threads) {
615*288bf522SAndroid Build Coastguard Worker   ThreadReportBuilder builder;
616*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(builder.AggregateThreads({"thread-pool.*"}));
617*288bf522SAndroid Build Coastguard Worker   ThreadEntry* thread = thread_tree.FindThread(1);
618*288bf522SAndroid Build Coastguard Worker   ThreadReport report = builder.Build(*thread);
619*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(IsReportEqual(report, ThreadReport(1, 1, "thread1")));
620*288bf522SAndroid Build Coastguard Worker   thread = thread_tree.FindThread(2);
621*288bf522SAndroid Build Coastguard Worker   report = builder.Build(*thread);
622*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(IsReportEqual(report, ThreadReport(1, 2, "thread-pool.*")));
623*288bf522SAndroid Build Coastguard Worker   thread = thread_tree.FindThread(3);
624*288bf522SAndroid Build Coastguard Worker   report = builder.Build(*thread);
625*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(IsReportEqual(report, ThreadReport(1, 2, "thread-pool.*")));
626*288bf522SAndroid Build Coastguard Worker }
627*288bf522SAndroid Build Coastguard Worker 
628*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(ThreadReportBuilderTest,aggregate_threads_bad_regex)629*288bf522SAndroid Build Coastguard Worker TEST_F(ThreadReportBuilderTest, aggregate_threads_bad_regex) {
630*288bf522SAndroid Build Coastguard Worker   ThreadReportBuilder builder;
631*288bf522SAndroid Build Coastguard Worker   ASSERT_FALSE(builder.AggregateThreads({"?thread-pool*"}));
632*288bf522SAndroid Build Coastguard Worker }
633