diff options
Diffstat (limited to 'simpleperf/cmd_record_test.cpp')
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 123 |
1 files changed, 96 insertions, 27 deletions
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index 01861c60..b8300d7f 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -98,15 +98,15 @@ static void CheckEventType(const std::string& record_file, const std::string& ev ASSERT_TRUE(type != nullptr); std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(record_file); ASSERT_TRUE(reader); - std::vector<EventAttrWithId> attrs = reader->AttrSection(); - for (auto& attr : attrs) { - if (attr.attr->type == type->type && attr.attr->config == type->config) { - if (attr.attr->freq == 0) { - ASSERT_EQ(sample_period, attr.attr->sample_period); + for (const auto& attr_with_id : reader->AttrSection()) { + const perf_event_attr& attr = attr_with_id.attr; + if (attr.type == type->type && attr.config == type->config) { + if (attr.freq == 0) { + ASSERT_EQ(sample_period, attr.sample_period); ASSERT_EQ(sample_freq, 0u); } else { ASSERT_EQ(sample_period, 0u); - ASSERT_EQ(sample_freq, attr.attr->sample_freq); + ASSERT_EQ(sample_freq, attr.sample_freq); } return; } @@ -192,6 +192,9 @@ TEST(record_cmd, rN_event) { } else if (GetTargetArch() == ARCH_X86_32 || GetTargetArch() == ARCH_X86_64) { // As in volume 3 chapter 19 of the Intel manual, 0x00c0 is the event number for instruction. event_number = 0x00c0; + } else if (GetTargetArch() == ARCH_RISCV64) { + // RISCV_PMU_INSTRET = 1 + event_number = 0x1; } else { GTEST_LOG_(INFO) << "Omit arch " << GetTargetArch(); return; @@ -201,10 +204,10 @@ TEST(record_cmd, rN_event) { ASSERT_TRUE(RunRecordCmd({"-e", event_name}, tmpfile.path)); std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile.path); ASSERT_TRUE(reader); - std::vector<EventAttrWithId> attrs = reader->AttrSection(); + const EventAttrIds& attrs = reader->AttrSection(); ASSERT_EQ(1u, attrs.size()); - ASSERT_EQ(PERF_TYPE_RAW, attrs[0].attr->type); - ASSERT_EQ(event_number, attrs[0].attr->config); + ASSERT_EQ(PERF_TYPE_RAW, attrs[0].attr.type); + ASSERT_EQ(event_number, attrs[0].attr.config); } TEST(record_cmd, branch_sampling) { @@ -254,7 +257,16 @@ TEST(record_cmd, dwarf_callchain_sampling) { ASSERT_TRUE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf"})); ASSERT_TRUE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf,16384"})); ASSERT_FALSE(RunRecordCmd({"-p", pid, "--call-graph", "dwarf,65536"})); - ASSERT_TRUE(RunRecordCmd({"-p", pid, "-g"})); + TemporaryFile tmpfile; + ASSERT_TRUE(RunRecordCmd({"-p", pid, "-g"}, tmpfile.path)); + auto reader = RecordFileReader::CreateInstance(tmpfile.path); + ASSERT_TRUE(reader); + const EventAttrIds& attrs = reader->AttrSection(); + ASSERT_GT(attrs.size(), 0); + // Check that reg and stack fields are removed after unwinding. + for (const auto& attr : attrs) { + ASSERT_EQ(attr.attr.sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER), 0); + } } TEST(record_cmd, system_wide_dwarf_callchain_sampling) { @@ -349,14 +361,16 @@ static void ProcessSymbolsInPerfDataFile( auto reader = RecordFileReader::CreateInstance(perf_data_file); ASSERT_TRUE(reader); FileFeature file; - size_t read_pos = 0; - while (reader->ReadFileFeature(read_pos, &file)) { + uint64_t read_pos = 0; + bool error = false; + while (reader->ReadFileFeature(read_pos, file, error)) { for (const auto& symbol : file.symbols) { if (callback(symbol, file.type)) { return; } } } + ASSERT_FALSE(error); } // Check if dumped symbols in perf.data matches our expectation. @@ -507,6 +521,7 @@ TEST(record_cmd, record_meta_info_feature) { auto& info_map = reader->GetMetaInfoFeature(); ASSERT_NE(info_map.find("simpleperf_version"), info_map.end()); ASSERT_NE(info_map.find("timestamp"), info_map.end()); + ASSERT_NE(info_map.find("record_stat"), info_map.end()); #if defined(__ANDROID__) ASSERT_NE(info_map.find("product_props"), info_map.end()); ASSERT_NE(info_map.find("android_version"), info_map.end()); @@ -546,7 +561,7 @@ TEST(record_cmd, trace_offcpu_option) { auto info_map = reader->GetMetaInfoFeature(); ASSERT_EQ(info_map["trace_offcpu"], "true"); if (IsSwitchRecordSupported()) { - ASSERT_EQ(reader->AttrSection()[0].attr->context_switch, 1); + ASSERT_EQ(reader->AttrSection()[0].attr.context_switch, 1); } // Release recording environment in perf.data, to avoid affecting tests below. reader.reset(); @@ -709,8 +724,9 @@ class RecordingAppHelper { bool RecordData(const std::string& record_cmd) { std::vector<std::string> args = android::base::Split(record_cmd, " "); - args.emplace_back("-o"); - args.emplace_back(perf_data_file_.path); + // record_cmd may end with child command. We should put output options before it. + args.emplace(args.begin(), "-o"); + args.emplace(args.begin() + 1, GetDataPath()); return RecordCmd()->Run(args); } @@ -722,10 +738,15 @@ class RecordingAppHelper { } return success; }; - ProcessSymbolsInPerfDataFile(perf_data_file_.path, callback); + ProcessSymbolsInPerfDataFile(GetDataPath(), callback); + if (!success) { + DumpData(); + } return success; } + void DumpData() { CreateCommandInstance("report")->Run({"-i", GetDataPath()}); } + std::string GetDataPath() const { return perf_data_file_.path; } private: @@ -763,7 +784,9 @@ static void TestRecordingApps(const std::string& app_name, const std::string& ap reader.reset(nullptr); // Check that simpleperf can't execute child command in app uid. - ASSERT_FALSE(helper.RecordData("--app " + app_name + " -e " + GetDefaultEvent() + " sleep 1")); + if (!IsRoot()) { + ASSERT_FALSE(helper.RecordData("--app " + app_name + " -e " + GetDefaultEvent() + " sleep 1")); + } } TEST(record_cmd, app_option_for_debuggable_app) { @@ -812,15 +835,18 @@ TEST(record_cmd, record_java_app) { } // Check perf.data by looking for java symbols. + const char* java_symbols[] = { + "androidx.test.runner", + "androidx.test.espresso", + "android.app.ActivityThread.main", + }; auto process_symbol = [&](const char* name) { -#if !defined(IN_CTS_TEST) - const char* expected_name_with_keyguard = "androidx.test.runner"; // when screen is locked - if (strstr(name, expected_name_with_keyguard) != nullptr) { - return true; + for (const char* java_symbol : java_symbols) { + if (strstr(name, java_symbol) != nullptr) { + return true; + } } -#endif - const char* expected_name = "androidx.test.espresso"; // when screen stays awake - return strstr(name, expected_name) != nullptr; + return false; }; ASSERT_TRUE(helper.CheckData(process_symbol)); #else @@ -930,9 +956,9 @@ TEST(record_cmd, cs_etm_event) { // cs-etm uses sample period instead of sample freq. ASSERT_EQ(reader->AttrSection().size(), 1u); - const perf_event_attr* attr = reader->AttrSection()[0].attr; - ASSERT_EQ(attr->freq, 0); - ASSERT_EQ(attr->sample_period, 1); + const perf_event_attr& attr = reader->AttrSection()[0].attr; + ASSERT_EQ(attr.freq, 0); + ASSERT_EQ(attr.sample_period, 1); bool has_auxtrace_info = false; bool has_auxtrace = false; @@ -1033,6 +1059,23 @@ TEST(record_cmd, addr_filter_option) { ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--addr-filter", filter})); } +TEST(record_cmd, decode_etm_option) { + if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) { + GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device"; + return; + } + ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--decode-etm"})); + ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--decode-etm", "--exclude-perf"})); +} + +TEST(record_cmd, binary_option) { + if (!ETMRecorder::GetInstance().CheckEtmSupport().ok()) { + GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device"; + return; + } + ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--decode-etm", "--binary", ".*"})); +} + TEST(record_cmd, pmu_event_option) { TEST_REQUIRE_PMU_COUNTER(); TEST_REQUIRE_HW_COUNTER(); @@ -1197,6 +1240,7 @@ TEST(record_cmd, add_meta_info_option) { } TEST(record_cmd, device_meta_info) { +#if defined(__ANDROID__) TemporaryFile tmpfile; ASSERT_TRUE(RunRecordCmd({}, tmpfile.path)); auto reader = RecordFileReader::CreateInstance(tmpfile.path); @@ -1209,6 +1253,9 @@ TEST(record_cmd, device_meta_info) { it = meta_info.find("android_build_type"); ASSERT_NE(it, meta_info.end()); ASSERT_FALSE(it->second.empty()); +#else + GTEST_LOG_(INFO) << "This test tests a function only available on Android."; +#endif } TEST(record_cmd, add_counter_option) { @@ -1231,3 +1278,25 @@ TEST(record_cmd, add_counter_option) { })); ASSERT_TRUE(has_sample); } + +TEST(record_cmd, user_buffer_size_option) { + ASSERT_TRUE(RunRecordCmd({"--user-buffer-size", "256M"})); +} + +TEST(record_cmd, record_process_name) { + TemporaryFile tmpfile; + ASSERT_TRUE(RecordCmd()->Run({"-e", GetDefaultEvent(), "-o", tmpfile.path, "sleep", SLEEP_SEC})); + std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile.path); + ASSERT_TRUE(reader); + bool has_comm = false; + ASSERT_TRUE(reader->ReadDataSection([&](std::unique_ptr<Record> r) { + if (r->type() == PERF_RECORD_COMM) { + CommRecord* cr = static_cast<CommRecord*>(r.get()); + if (strcmp(cr->comm, "sleep") == 0) { + has_comm = true; + } + } + return true; + })); + ASSERT_TRUE(has_comm); +} |