xref: /aosp_15_r20/system/extras/simpleperf/cmd_debug_unwind_test.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1 /*
2  * Copyright (C) 2018 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 <gtest/gtest.h>
18 
19 #include <unistd.h>
20 
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include <android-base/file.h>
26 
27 #include "command.h"
28 #include "get_test_data.h"
29 #include "record_file.h"
30 #include "test_util.h"
31 
32 using namespace simpleperf;
33 
DebugUnwindCmd()34 static std::unique_ptr<Command> DebugUnwindCmd() {
35   return CreateCommandInstance("debug-unwind");
36 }
37 
38 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,unwind_sample_option)39 TEST(cmd_debug_unwind, unwind_sample_option) {
40   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
41   CaptureStdout capture;
42 
43   ASSERT_TRUE(capture.Start());
44   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--unwind-sample"}));
45   ASSERT_NE(capture.Finish().find("sample_time: 1516379654300997"), std::string::npos);
46 }
47 
48 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,sample_time_option)49 TEST(cmd_debug_unwind, sample_time_option) {
50   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
51   CaptureStdout capture;
52 
53   ASSERT_TRUE(capture.Start());
54   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--unwind-sample", "--sample-time",
55                                      "1516379654300997", "--sample-time",
56                                      "1516379654363914,1516379655959122"}));
57   std::string output = capture.Finish();
58   ASSERT_NE(output.find("sample_time: 1516379654300997"), std::string::npos);
59   ASSERT_NE(output.find("sample_time: 1516379654363914"), std::string::npos);
60   ASSERT_NE(output.find("sample_time: 1516379655959122"), std::string::npos);
61 }
62 
63 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,output_option)64 TEST(cmd_debug_unwind, output_option) {
65   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
66   TemporaryFile tmpfile;
67   close(tmpfile.release());
68   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--unwind-sample", "--sample-time",
69                                      "1516379654300997", "-o", tmpfile.path}));
70   std::string output;
71   ASSERT_TRUE(android::base::ReadFileToString(tmpfile.path, &output));
72   ASSERT_NE(output.find("sample_time: 1516379654300997"), std::string::npos);
73 }
74 
75 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,symfs_option)76 TEST(cmd_debug_unwind, symfs_option) {
77   std::string input_data = GetTestData(NATIVELIB_IN_APK_PERF_DATA);
78   CaptureStdout capture;
79   ASSERT_TRUE(capture.Start());
80   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--symfs", GetTestDataDir(),
81                                      "--unwind-sample", "--sample-time", "500329355223"}));
82   ASSERT_NE(capture.Finish().find(
83                 "dso_4: /data/app/com.example.hellojni-1/base.apk!/lib/arm64-v8a/libhello-jni.so"),
84             std::string::npos);
85 }
86 
87 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,unwind_with_ip_zero_in_callchain)88 TEST(cmd_debug_unwind, unwind_with_ip_zero_in_callchain) {
89   CaptureStdout capture;
90   ASSERT_TRUE(capture.Start());
91   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", GetTestData(PERF_DATA_WITH_IP_ZERO_IN_CALLCHAIN),
92                                      "--unwind-sample", "--sample-time", "152526249937103"}));
93   ASSERT_NE(capture.Finish().find("sample_time: 152526249937103"), std::string::npos);
94 }
95 
96 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,unwind_embedded_lib_in_apk)97 TEST(cmd_debug_unwind, unwind_embedded_lib_in_apk) {
98   // Check if we can unwind through a native library embedded in an apk. In the profiling data
99   // file, there is a sample with ip address pointing to
100   // /data/app/simpleperf.demo.cpp_api/base.apk!/lib/arm64-v8a/libnative-lib.so.
101   // If unwound successfully, it can reach a function in libc.so.
102   CaptureStdout capture;
103   ASSERT_TRUE(capture.Start());
104   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", GetTestData("perf_unwind_embedded_lib_in_apk.data"),
105                                      "--symfs", GetTestDataDir(), "--unwind-sample",
106                                      "--sample-time", "20345907755421"}));
107   std::string output = capture.Finish();
108   ASSERT_NE(
109       output.find(
110           "dso_1: /data/app/simpleperf.demo.cpp_api/base.apk!/lib/arm64-v8a/libnative-lib.so"),
111       std::string::npos)
112       << output;
113   ASSERT_NE(output.find("dso_2: /bionic/lib64/libc.so"), std::string::npos) << output;
114 }
115 
116 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,unwind_sample_in_unwinding_debug_info_file)117 TEST(cmd_debug_unwind, unwind_sample_in_unwinding_debug_info_file) {
118   CaptureStdout capture;
119   ASSERT_TRUE(capture.Start());
120   ASSERT_TRUE(DebugUnwindCmd()->Run(
121       {"-i", GetTestData("perf_with_failed_unwinding_debug_info.data"), "--unwind-sample"}));
122   std::string output = capture.Finish();
123   ASSERT_NE(output.find("symbol_5: android.os.Handler.post"), std::string::npos) << output;
124 }
125 
126 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,skip_sample_print_option)127 TEST(cmd_debug_unwind, skip_sample_print_option) {
128   std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
129   CaptureStdout capture;
130 
131   ASSERT_TRUE(capture.Start());
132   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--unwind-sample", "--skip-sample-print"}));
133 
134   std::string output = capture.Finish();
135   ASSERT_EQ(output.find("sample_time:"), std::string::npos);
136   ASSERT_NE(output.find("unwinding_sample_count: 8"), std::string::npos);
137 }
138 
139 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,generate_test_file)140 TEST(cmd_debug_unwind, generate_test_file) {
141   TemporaryFile tmpfile;
142   close(tmpfile.release());
143   ASSERT_TRUE(DebugUnwindCmd()->Run(
144       {"-i", GetTestData("perf_with_failed_unwinding_debug_info.data"), "--generate-test-file",
145        "--sample-time", "626968783364202", "-o", tmpfile.path, "--keep-binaries-in-test-file",
146        "perf.data_jit_app_cache:255984-259968,perf.data_jit_app_cache:280144-283632"}));
147 
148   CaptureStdout capture;
149   ASSERT_TRUE(capture.Start());
150   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", tmpfile.path, "--unwind-sample"}));
151   std::string output = capture.Finish();
152   ASSERT_NE(output.find("symbol_2: android.os.Handler.enqueueMessage"), std::string::npos);
153 }
154 
155 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,generate_test_file_with_build_id)156 TEST(cmd_debug_unwind, generate_test_file_with_build_id) {
157   TemporaryFile tmpfile;
158   close(tmpfile.release());
159   ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", GetTestData("perf_display_bitmaps.data"),
160                                      "--generate-test-file", "--sample-time", "684943450156904",
161                                      "-o", tmpfile.path, "--keep-binaries-in-test-file",
162                                      "/apex/com.android.runtime/lib64/bionic/libc.so"}));
163   auto reader = RecordFileReader::CreateInstance(tmpfile.path);
164   ASSERT_TRUE(reader);
165   auto build_ids = reader->ReadBuildIdFeature();
166   ASSERT_EQ(build_ids.size(), 1);
167   ASSERT_STREQ(build_ids[0].filename, "/apex/com.android.runtime/lib64/bionic/libc.so");
168 }
169 
170 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,generate_report)171 TEST(cmd_debug_unwind, generate_report) {
172   TemporaryFile tmpfile;
173   close(tmpfile.release());
174   ASSERT_TRUE(
175       DebugUnwindCmd()->Run({"-i", GetTestData("perf_with_failed_unwinding_debug_info.data"),
176                              "--generate-report", "-o", tmpfile.path}));
177   std::string output;
178   ASSERT_TRUE(android::base::ReadFileToString(tmpfile.path, &output));
179   ASSERT_NE(output.find("unwinding_error_code: 4"), std::string::npos);
180   ASSERT_NE(output.find("symbol_2: android.os.Handler.enqueueMessage"), std::string::npos);
181 }
182 
183 // @CddTest = 6.1/C-0-2
TEST(cmd_debug_unwind,unwind_sample_for_small_map_range)184 TEST(cmd_debug_unwind, unwind_sample_for_small_map_range) {
185   CaptureStdout capture;
186   ASSERT_TRUE(capture.Start());
187   ASSERT_TRUE(DebugUnwindCmd()->Run(
188       {"-i", GetTestData("debug_unwind_small_map_range.data"), "--unwind-sample"}));
189   std::string output = capture.Finish();
190   ASSERT_NE(output.find("dso_3: /apex/com.android.art/lib64/libart.so"), std::string::npos)
191       << output;
192 }
193