1 /* 2 * Copyright (C) 2016 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 <android-base/file.h> 20 21 #include "command.h" 22 #include "get_test_data.h" 23 24 static std::unique_ptr<Command> ReportSampleCmd() { 25 return CreateCommandInstance("report-sample"); 26 } 27 28 TEST(cmd_report_sample, text) { 29 ASSERT_TRUE( 30 ReportSampleCmd()->Run({"-i", GetTestData(PERF_DATA_WITH_SYMBOLS)})); 31 } 32 33 TEST(cmd_report_sample, output_option) { 34 TemporaryFile tmpfile; 35 ASSERT_TRUE(ReportSampleCmd()->Run( 36 {"-i", GetTestData(PERF_DATA_WITH_SYMBOLS), "-o", tmpfile.path})); 37 } 38 39 TEST(cmd_report_sample, show_callchain_option) { 40 TemporaryFile tmpfile; 41 ASSERT_TRUE(ReportSampleCmd()->Run({"-i", GetTestData(CALLGRAPH_FP_PERF_DATA), 42 "-o", tmpfile.path, "--show-callchain"})); 43 } 44 45 static void GetProtobufReport(const std::string& test_data_file, std::string* protobuf_report, 46 const std::vector<std::string>& extra_args = {}) { 47 TemporaryFile tmpfile; 48 TemporaryFile tmpfile2; 49 std::vector<std::string> args = {"-i", GetTestData(test_data_file), "-o", tmpfile.path, 50 "--protobuf"}; 51 args.insert(args.end(), extra_args.begin(), extra_args.end()); 52 ASSERT_TRUE(ReportSampleCmd()->Run(args)); 53 ASSERT_TRUE(ReportSampleCmd()->Run({"--dump-protobuf-report", tmpfile.path, 54 "-o", tmpfile2.path})); 55 ASSERT_TRUE(android::base::ReadFileToString(tmpfile2.path, protobuf_report)); 56 } 57 58 TEST(cmd_report_sample, protobuf_option) { 59 std::string data; 60 GetProtobufReport(PERF_DATA_WITH_SYMBOLS, &data); 61 ASSERT_NE(data.find("magic: SIMPLEPERF"), std::string::npos); 62 ASSERT_NE(data.find("version: 1"), std::string::npos); 63 ASSERT_NE(data.find("file:"), std::string::npos); 64 } 65 66 TEST(cmd_report_sample, no_skipped_file_id) { 67 std::string data; 68 GetProtobufReport(PERF_DATA_WITH_WRONG_IP_IN_CALLCHAIN, &data); 69 // If wrong ips in callchain are omitted, "unknown" file path will not be generated. 70 ASSERT_EQ(data.find("unknown"), std::string::npos); 71 } 72 73 TEST(cmd_report_sample, sample_has_event_count) { 74 std::string data; 75 GetProtobufReport(PERF_DATA_WITH_SYMBOLS, &data); 76 ASSERT_NE(data.find("event_count:"), std::string::npos); 77 } 78 79 TEST(cmd_report_sample, has_thread_record) { 80 std::string data; 81 GetProtobufReport(PERF_DATA_WITH_SYMBOLS, &data); 82 ASSERT_NE(data.find("thread:"), std::string::npos); 83 ASSERT_NE(data.find("thread_name: t2"), std::string::npos); 84 } 85 86 TEST(cmd_report_sample, trace_offcpu) { 87 std::string data; 88 GetProtobufReport(PERF_DATA_WITH_TRACE_OFFCPU, &data); 89 ASSERT_NE(data.find("event_type: sched:sched_switch"), std::string::npos); 90 } 91 92 TEST(cmd_report_sample, have_clear_callchain_end_in_protobuf_output) { 93 std::string data; 94 GetProtobufReport(PERF_DATA_WITH_TRACE_OFFCPU, &data, {"--show-callchain"}); 95 ASSERT_NE(data.find("__libc_init"), std::string::npos); 96 ASSERT_EQ(data.find("_start_main"), std::string::npos); 97 } 98 99 TEST(cmd_report_sample, app_package_name_in_meta_info) { 100 std::string data; 101 GetProtobufReport(PERF_DATA_WITH_APP_PACKAGE_NAME, &data); 102 ASSERT_NE(data.find("app_package_name: com.google.sample.tunnel"), std::string::npos); 103 } 104 105 TEST(cmd_report_sample, remove_unknown_kernel_symbols) { 106 std::string data; 107 // Test --remove-unknown-kernel-symbols on perf.data with kernel_symbols_available=false. 108 GetProtobufReport(PERF_DATA_WITH_KERNEL_SYMBOLS_AVAILABLE_FALSE, &data, 109 {"--show-callchain"}); 110 ASSERT_NE(data.find("time: 1368182962424044"), std::string::npos); 111 ASSERT_NE(data.find("path: [kernel.kallsyms]"), std::string::npos); 112 ASSERT_NE(data.find("path: /system/lib64/libc.so"), std::string::npos); 113 GetProtobufReport(PERF_DATA_WITH_KERNEL_SYMBOLS_AVAILABLE_FALSE, &data, 114 {"--show-callchain", "--remove-unknown-kernel-symbols"}); 115 // The sample dumped at time 1368182962424044 shouldn't be removed. Because it has user space 116 // callchains. 117 ASSERT_NE(data.find("time: 1368182962424044"), std::string::npos); 118 // Kernel callchains shouldn't be removed. 119 ASSERT_EQ(data.find("path: [kernel.kallsyms]"), std::string::npos); 120 // User space callchains still exist. 121 ASSERT_NE(data.find("path: /system/lib64/libc.so"), std::string::npos); 122 123 // Test --remove-unknown-kernel-symbols on perf.data with kernel_symbols_available=true. 124 GetProtobufReport(PERF_DATA_WITH_KERNEL_SYMBOLS_AVAILABLE_TRUE, &data, 125 {"--show-callchain"}); 126 ASSERT_NE(data.find("time: 1368297633794862"), std::string::npos); 127 ASSERT_NE(data.find("path: [kernel.kallsyms]"), std::string::npos); 128 ASSERT_NE(data.find("symbol: binder_ioctl_write_read"), std::string::npos); 129 ASSERT_NE(data.find("path: /system/lib64/libc.so"), std::string::npos); 130 GetProtobufReport(PERF_DATA_WITH_KERNEL_SYMBOLS_AVAILABLE_TRUE, &data, 131 {"--show-callchain", "--remove-unknown-kernel-symbols"}); 132 ASSERT_NE(data.find("time: 1368297633794862"), std::string::npos); 133 ASSERT_NE(data.find("path: [kernel.kallsyms]"), std::string::npos); 134 ASSERT_NE(data.find("symbol: binder_ioctl_write_read"), std::string::npos); 135 ASSERT_NE(data.find("path: /system/lib64/libc.so"), std::string::npos); 136 } 137 138 TEST(cmd_report_sample, show_art_frames_option) { 139 std::string data; 140 GetProtobufReport(PERF_DATA_WITH_INTERPRETER_FRAMES, &data, {"--show-callchain"}); 141 ASSERT_EQ(data.find("artMterpAsmInstructionStart"), std::string::npos); 142 GetProtobufReport(PERF_DATA_WITH_INTERPRETER_FRAMES, &data, 143 {"--show-callchain", "--show-art-frames"}); 144 ASSERT_NE(data.find("artMterpAsmInstructionStart"), std::string::npos); 145 } 146 147 TEST(cmd_report_sample, show_symbols_before_and_after_demangle) { 148 std::string data; 149 GetProtobufReport(PERF_DATA_WITH_INTERPRETER_FRAMES, &data, {"--show-callchain"}); 150 ASSERT_NE(data.find("symbol: android::hardware::IPCThreadState::talkWithDriver(bool)"), 151 std::string::npos); 152 ASSERT_NE(data.find("mangled_symbol: _ZN7android8hardware14IPCThreadState14talkWithDriverEb"), 153 std::string::npos); 154 } 155 156 TEST(cmd_report_sample, symdir_option) { 157 std::string data; 158 GetProtobufReport(PERF_DATA_FOR_BUILD_ID_CHECK, &data); 159 ASSERT_EQ(data.find("symbol: main"), std::string::npos); 160 GetProtobufReport(PERF_DATA_FOR_BUILD_ID_CHECK, &data, 161 {"--symdir", GetTestDataDir() + CORRECT_SYMFS_FOR_BUILD_ID_CHECK}); 162 ASSERT_NE(data.find("symbol: main"), std::string::npos); 163 } 164