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