diff --git a/include/perf_event_record.h b/include/perf_event_record.h index 4c41955a22fad510152ffdcb74f942a37fb0cfaf..cc158320e226e7ff8dbfe47c94e51120fe9aced2 100644 --- a/include/perf_event_record.h +++ b/include/perf_event_record.h @@ -61,10 +61,16 @@ static constexpr char PERF_RECORD_TYPE_ITRACESTART[] = "itraceStart"; static constexpr char PERF_RECORD_TYPE_LOSTSAMPLE[] = "lostSamples"; static constexpr char PERF_RECORD_TYPE_SWITCH[] = "switch"; static constexpr char PERF_RECORD_TYPE_SWITCHCPUWIDE[] = "switchCpuWide"; +static constexpr char PERF_RECORD_TYPE_AUXTRACEINFO[] = "auxtraceinfo"; +static constexpr char PERF_RECORD_TYPE_TIMECONV[] = "timeconv"; +static constexpr char PERF_RECORD_TYPE_CPUMAP[] = "cpumap"; static constexpr char* PERF_RECORD_TYPE_NULL = nullptr; enum perf_event_hiperf_ext_type { + PERF_RECORD_AUXTRACE_INFO = 70, PERF_RECORD_AUXTRACE = 71, + PERF_RECORD_CPU_MAP = 74, + PERF_RECORD_TIME_CONV = 79, PERF_RECORD_HIPERF_CALLSTACK = UINT32_MAX / 2, }; @@ -185,6 +191,28 @@ public: size_t GetSize() const override; }; +class PerfRecordAuxTraceInfo : public PerfEventRecordTemplate { +public: + PerfRecordAuxTraceInfo() = default; + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +class PerfRecordTimeConv : public PerfEventRecordTemplate { +public: + PerfRecordTimeConv() = default; + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +class PerfRecordCpuMap : public PerfEventRecordTemplate { +public: + PerfRecordCpuMap() = default; + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + class PerfRecordMmap : public PerfEventRecordTemplate { public: PerfRecordMmap() = default; diff --git a/include/perf_file_writer.h b/include/perf_file_writer.h index f027c943b097c14349ed0aaf171b743bb5a91dc2..28fff0185552a0a2371b07debb73b032b5f5ad75 100644 --- a/include/perf_file_writer.h +++ b/include/perf_file_writer.h @@ -45,7 +45,7 @@ public: bool Open(const std::string &fileName, bool compressData = false); // WriteAttrAndId() must be called before WriteRecord() - bool WriteAttrAndId(const std::vector &attrIds); + bool WriteAttrAndId(const std::vector &attrIds, bool isSpe = false); bool WriteRecord(const PerfEventRecord &record); bool AddNrCpusFeature(FEATURE feature, uint32_t nrCpusAvailable, uint32_t nrCpusOnline); bool AddEventDescFeature(FEATURE feature, const std::vector &eventDesces); @@ -74,6 +74,7 @@ private: bool Write(const void *buf, size_t len); bool WriteHeader(); bool WriteFeatureData(); + bool WriteAuxTraceEvent(bool isSpe); std::string fileName_; FILE *fp_ = nullptr; diff --git a/include/perf_record_format.h b/include/perf_record_format.h index c5453272a9308d58bf4e64796d9509223628ab84..8e4cb97ec7a22df6bd775a640b913251dedae82a 100644 --- a/include/perf_record_format.h +++ b/include/perf_record_format.h @@ -55,6 +55,9 @@ struct PerfRecordAuxtraceData { u32 tid = 0; u32 cpu = 0; u32 reserved__ = 0; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif }; /* @@ -380,6 +383,30 @@ struct PerfRecordNamespacesData { struct sample_id sample_id; #endif }; + +struct PerfRecordTtimeConvData { + u64 time_shift; + u64 time_mult; + u64 time_zero; + u64 time_cycles; + u64 time_mask; + u8 cap_user_time_zero; + u8 cap_user_time_short; + u8 reserved[6]; // 6 : For alignment +}; + +struct PerfRecordAuxtraceInfoData { + u32 type; + u32 reserved; + u64 priv[2]; +}; + +struct PerfRecordCpuMapData { + u16 type; + u16 nr; + u16 cpu[16]; // 16 : cpus + u8 reserved[4]; // 4 : For alignment +}; } // namespace HiPerf } // namespace Developtools } // namespace OHOS diff --git a/include/spe_decoder.h b/include/spe_decoder.h index 653bdba63e57d4c8b667f520d61eb427b2340175..012235b50285c252ddded1c5989289d6b1848468 100644 --- a/include/spe_decoder.h +++ b/include/spe_decoder.h @@ -63,6 +63,15 @@ enum SpePktType { PERF_SPE_DATA_SOURCE, }; +enum AuxTraceType { + HIPERF_AUXTRACE_UNKNOWN, + HIPERF_AUXTRACE_INTEL_PT, + HIPERF_AUXTRACE_INTEL_BTS, + HIPERF_AUXTRACE_CS_ETM, + HIPERF_AUXTRACE_ARM_SPE, + HIPERF_AUXTRACE_S390_CPUMSF, +}; + struct SpePkt { SpePktType type; unsigned char index; diff --git a/include/subcommand_record.h b/include/subcommand_record.h index ea12baa30f5927675a1b9991464b936066a76fe5..a98826a0cc19b1a1edce0b27a7a0f880441fc81a 100644 --- a/include/subcommand_record.h +++ b/include/subcommand_record.h @@ -217,6 +217,7 @@ public: {"store_filter", 0}, {"ts_enable", 0}, {"pa_enable", 0}, {"jitter", 0}, {"min_latency", 0}, {"event_filter", 0}, + {"pct_enable", 0}, }; static SubCommand& GetInstance(); @@ -255,7 +256,6 @@ private: std::vector selectTids_ = {}; bool restart_ = false; std::vector selectEvents_ = {}; - std::vector speOptions_ = {}; std::vector> selectGroups_ = {}; std::vector callStackType_ = {}; std::vector vecBranchFilters_ = {}; @@ -388,6 +388,7 @@ private: bool CheckTargetPids(); bool CheckReportOption(); bool CheckBacktrackOption(); + bool CheckSpeOption(); void WriteCommEventBeforeSampling(); void RemoveVdsoTmpFile(); diff --git a/src/perf_event_record.cpp b/src/perf_event_record.cpp index 95bad19c1745218ca873a5dde902a3912dfbcba6..b9a94d40624d17457691edd52601f74e9ec567e0 100644 --- a/src/perf_event_record.cpp +++ b/src/perf_event_record.cpp @@ -57,6 +57,12 @@ static PerfEventRecord* CreatePerfEventRecord(PerfRecordType type) return new PerfRecordAux(); case PERF_RECORD_AUXTRACE: return new PerfRecordAuxtrace(); + case PERF_RECORD_AUXTRACE_INFO: + return new PerfRecordAuxTraceInfo(); + case PERF_RECORD_TIME_CONV: + return new PerfRecordTimeConv(); + case PERF_RECORD_CPU_MAP: + return new PerfRecordCpuMap(); case PERF_RECORD_ITRACE_START: return new PerfRecordItraceStart(); case PERF_RECORD_LOST_SAMPLES: @@ -1000,6 +1006,60 @@ void PerfRecordAux::DumpData(int indent) const data_.sample_id.time); } +bool PerfRecordAuxTraceInfo::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + std::copy(reinterpret_cast(&data_), + reinterpret_cast(&data_) + GetSize() - GetHeaderSize(), p); + return true; +} + +void PerfRecordAuxTraceInfo::DumpData(int indent) const +{ + PRINT_INDENT(indent, "aux_trace_event"); +} + +bool PerfRecordTimeConv::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + std::copy(reinterpret_cast(&data_), + reinterpret_cast(&data_) + GetSize() - GetHeaderSize(), p); + return true; +} + +void PerfRecordTimeConv::DumpData(int indent) const +{ + PRINT_INDENT(indent, "aux_time_event"); +} + +bool PerfRecordCpuMap::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + std::copy(reinterpret_cast(&data_), + reinterpret_cast(&data_) + GetSize() - GetHeaderSize(), p); + return true; +} + +void PerfRecordCpuMap::DumpData(int indent) const +{ + PRINT_INDENT(indent, "cpu_map_event"); +} + bool PerfRecordItraceStart::GetBinary(std::vector &buf) const { if (buf.size() < GetSize()) { diff --git a/src/perf_events.cpp b/src/perf_events.cpp index 0d888ba0018150e018f1acbaa260385751a9e9be..9356fdad39a174ce463d00202bb92ffc7e2feada 100644 --- a/src/perf_events.cpp +++ b/src/perf_events.cpp @@ -389,21 +389,36 @@ bool PerfEvents::AddSpeEvent(u32 type, bool followGroup) eventItem.attr.size = sizeof(perf_event_attr); eventItem.attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; eventItem.attr.inherit = (inherit_ ? 1 : 0); - eventItem.attr.sample_type = SAMPLE_ID; + eventItem.attr.sample_type = SAMPLE_ID | PERF_SAMPLE_IP; eventItem.attr.sample_id_all = 1; eventItem.attr.disabled = 1; - eventItem.attr.config = 0x700010007; // temp type + eventItem.attr.config = 0x700010007; // enable all + if (config_ != 0) { + eventItem.attr.config = config_; + } + if (config1_ != 0) { + eventItem.attr.config1 = config1_; + } + if (config2_ != 0) { + eventItem.attr.config2 = config2_; + } + HLOGD("config_ is 0x%llx, config1_ is 0x%llx, config2_ is 0x%llx", + config_, config1_, config2_); return true; } void PerfEvents::SetConfig(std::map &speOptMaps) { - int jitterOffset = 16; - int branchOffset = 32; - int loadOffset = 33; - int storeOffset = 34; - config_ |= (speOptMaps["ts_enable"] & 0x1) << 0; - config_ |= (speOptMaps["pa_enable"] & 0x1) << 1; + constexpr int tsOffset = 0; + constexpr int paOffset = 1; + constexpr int pctOffset = 2; + constexpr int jitterOffset = 16; + constexpr int branchOffset = 32; + constexpr int loadOffset = 33; + constexpr int storeOffset = 34; + config_ |= (speOptMaps["ts_enable"] & 0x1) << tsOffset; + config_ |= (speOptMaps["pa_enable"] & 0x1) << paOffset; + config_ |= (speOptMaps["pct_enable"] & 0x1) << pctOffset; config_ |= (speOptMaps["jitter"] & 0x1) << jitterOffset; config_ |= (speOptMaps["branch_filter"] & 0x1) << branchOffset; config_ |= (speOptMaps["load_filter"] & 0x1) << loadOffset; diff --git a/src/perf_file_writer.cpp b/src/perf_file_writer.cpp index 72913a4d397e926628078c81e5d76820c60ea007..2a8c873e5c9f54c0bc10ac43919c99e245cb22f3 100644 --- a/src/perf_file_writer.cpp +++ b/src/perf_file_writer.cpp @@ -19,6 +19,7 @@ #include #include "hiperf_hilog.h" +#include "spe_decoder.h" #include "utilities.h" using namespace std::chrono; @@ -252,7 +253,7 @@ bool PerfFileWriter::Write(const void *buf, size_t len) return true; } -bool PerfFileWriter::WriteAttrAndId(const std::vector &attrIds) +bool PerfFileWriter::WriteAttrAndId(const std::vector &attrIds, bool isSpe) { CHECK_TRUE(attrIds.empty(), false, 0, ""); @@ -298,9 +299,64 @@ bool PerfFileWriter::WriteAttrAndId(const std::vector &attrIds) dataSection_.offset = dataSectionOffset; defaultEventAttr_ = attrIds[0].attr; - + if (!WriteAuxTraceEvent(isSpe)) { + HLOGE("WriteAuxTraceEvent failed"); + return false; + } isWritingRecord = true; + return true; +} +bool PerfFileWriter::WriteAuxTraceEvent(bool isSpe) +{ + if (isSpe) { + // the following events just for perf parse hiperf spe data + perf_event_header header; + PerfRecordTtimeConvData auxTimeConv; + header.type = PERF_RECORD_TIME_CONV; + header.size = sizeof(perf_event_header) + sizeof(PerfRecordTtimeConvData); + auxTimeConv.time_shift = 21; // 21 : time shift + auxTimeConv.time_mult = 1; + auxTimeConv.time_zero = 1; + auxTimeConv.time_cycles = 1; + auxTimeConv.cap_user_time_zero = 1; + auxTimeConv.cap_user_time_short = 1; + if (!Write(&header, sizeof(header))) { + return false; + } + if (!Write(&auxTimeConv, sizeof(auxTimeConv))) { + return false; + } + PerfRecordAuxtraceInfoData auxTraceEvent; + header.type = PERF_RECORD_AUXTRACE_INFO; + header.size = sizeof(perf_event_header) + sizeof(PerfRecordAuxtraceInfoData); + auxTraceEvent.type = HIPERF_AUXTRACE_ARM_SPE; + auxTraceEvent.priv[0] = 7; // 7 : arm spe type + auxTraceEvent.priv[1] = 2; // 2: cpu mmaps + if (!Write(&header, sizeof(header))) { + return false; + } + if (!Write(&auxTraceEvent, sizeof(auxTraceEvent))) { + return false; + } + + PerfRecordCpuMapData cpuMap; + header.type = PERF_RECORD_CPU_MAP; + header.size = sizeof(perf_event_header) + sizeof(PerfRecordCpuMapData); + cpuMap.nr = 16; // 16 : cpus + for (int i = 0; i < cpuMap.nr; i++) { + cpuMap.cpu[i] = i; + } + if (!Write(&header, sizeof(header))) { + return false; + } + if (!Write(&cpuMap, sizeof(cpuMap))) { + return false; + } + dataSection_.size = dataSection_.size + sizeof(perf_event_header) + sizeof(auxTimeConv) + + sizeof(perf_event_header) + sizeof(auxTraceEvent) + + sizeof(perf_event_header) + sizeof(cpuMap); + } return true; } diff --git a/src/subcommand_record.cpp b/src/subcommand_record.cpp index 1169c105851c90956d014d67596e8d2ba50cf556..26a3c8ba0a5476ade4e7baf4aed2a07e7f698466 100644 --- a/src/subcommand_record.cpp +++ b/src/subcommand_record.cpp @@ -188,15 +188,12 @@ bool SubCommandRecord::GetSpeOptions() for (auto item: valueExpressions) { std::vector expressions = StringSplit(item, "="); size_t itemNum = 2; - if (expressions.size() == itemNum && IsNumeric(expressions[1])) { + if (expressions.size() == itemNum && (IsNumeric(expressions[1]) || IsHexDigits(expressions[1]))) { std::string name = expressions[0]; unsigned long long num = std::stoull(expressions[1]); if (speOptMap_.find(name) != speOptMap_.end()) { speOptMap_[name] = num; } - if (num != 0) { - speOptions_.emplace_back(name); - } } } } @@ -540,6 +537,9 @@ bool SubCommandRecord::CheckOptions() if (!CheckBacktrackOption()) { return false; } + if (!CheckSpeOption()) { + return false; + } return true; } @@ -659,6 +659,23 @@ bool SubCommandRecord::CheckBacktrackOption() return true; } +bool SubCommandRecord::CheckSpeOption() +{ + constexpr uint64_t disable = 0; + constexpr uint64_t enable = 1; + std::vector optionNames = {"ts_enable", "pa_enable", "pct_enable", + "jitter", "branch_filter", "load_filter", + "store_filter"}; + for (auto optionName : optionNames) { + if (CheckOutOfRange(speOptMap_[optionName], disable, enable)) { + printf("Invalid %s value '%llu', value should be 0 or 1\n", + optionName.c_str(), speOptMap_[optionName]); + return false; + } + } + return true; +} + bool SubCommandRecord::ParseDataLimitOption(const std::string &str) { uint unit = 1; @@ -1777,7 +1794,7 @@ bool SubCommandRecord::CreateInitRecordFile(bool compressData) return false; } - CHECK_TRUE(!fileWriter_->WriteAttrAndId(perfEvents_.GetAttrWithId()), false, 0, ""); + CHECK_TRUE(!fileWriter_->WriteAttrAndId(perfEvents_.GetAttrWithId(), isSpe_), false, 0, ""); CHECK_TRUE(!AddFeatureRecordFile(), false, 0, ""); diff --git a/test/unittest/common/native/perf_event_record_test.cpp b/test/unittest/common/native/perf_event_record_test.cpp index eda941e7631abefd4b06f856103062f86bc9decf..bb4fe1794104a8b3a4fa302a65e7f9e6ca21d662 100644 --- a/test/unittest/common/native/perf_event_record_test.cpp +++ b/test/unittest/common/native/perf_event_record_test.cpp @@ -985,6 +985,76 @@ HWTEST_F(PerfEventRecordTest, GetTime, TestSize.Level1) sample.data_.time = time; EXPECT_EQ(sample.GetTime(), time); } + +HWTEST_F(PerfEventRecordTest, AuxTraceInfo, TestSize.Level1) +{ + constexpr uint32_t type = 4; + constexpr uint32_t reserve = 0; + constexpr uint64_t speType = 7; + constexpr uint64_t cpuMmap = 2; + struct PerfRecordAuxTraceInfost { + perf_event_header h; + PerfRecordAuxtraceInfoData d; + }; + PerfRecordAuxTraceInfost data = {{PERF_RECORD_AUXTRACE_INFO, PERF_RECORD_MISC_KERNEL, + sizeof(PerfRecordAuxTraceInfost)}, + {type, reserve, {speType, cpuMmap}}}; + + PerfRecordAuxTraceInfo record; + record.Init((uint8_t *)&data); + ASSERT_EQ(record.GetType(), PERF_RECORD_AUXTRACE_INFO); + ASSERT_EQ(record.GetName(), PERF_RECORD_TYPE_AUXTRACEINFO); + ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL); + ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE); + ASSERT_EQ(record.GetSize(), sizeof(data)); + ASSERT_EQ(record.data_.type, type); + ASSERT_EQ(record.data_.priv[0], speType); + ASSERT_EQ(record.data_.priv[1], cpuMmap); +} + +HWTEST_F(PerfEventRecordTest, TimeConv, TestSize.Level1) +{ + constexpr uint64_t timeShift = 21; + constexpr uint64_t timeDefalult = 1; + constexpr uint8_t userTime = 1; + struct PerfRecordTimeConvst { + perf_event_header h; + PerfRecordTtimeConvData d; + }; + PerfRecordTimeConvst data = {{PERF_RECORD_TIME_CONV, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordTimeConvst)}, + {timeShift, timeDefalult, timeDefalult, timeDefalult, timeDefalult, userTime}}; + + PerfRecordTimeConv record; + record.Init((uint8_t *)&data); + ASSERT_EQ(record.GetType(), PERF_RECORD_TIME_CONV); + ASSERT_EQ(record.GetName(), PERF_RECORD_TYPE_TIMECONV); + ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL); + ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE); + ASSERT_EQ(record.GetSize(), sizeof(data)); + ASSERT_EQ(record.data_.time_shift, timeShift); + ASSERT_EQ(record.data_.time_mult, timeDefalult); +} + +HWTEST_F(PerfEventRecordTest, CpuMap, TestSize.Level1) +{ + constexpr uint16_t type = 0; + constexpr uint16_t cpuNum = 16; + struct PerfRecordCpuMapst { + perf_event_header h; + PerfRecordCpuMapData d; + }; + PerfRecordCpuMapst data = {{PERF_RECORD_CPU_MAP, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordCpuMapst)}, + {type, cpuNum}}; + + PerfRecordCpuMap record; + record.Init((uint8_t *)&data); + ASSERT_EQ(record.GetType(), PERF_RECORD_CPU_MAP); + ASSERT_EQ(record.GetName(), PERF_RECORD_TYPE_CPUMAP); + ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL); + ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE); + ASSERT_EQ(record.GetSize(), sizeof(data)); + ASSERT_EQ(record.data_.nr, cpuNum); +} } // namespace HiPerf } // namespace Developtools } // namespace OHOS diff --git a/test/unittest/common/native/perf_events_test.cpp b/test/unittest/common/native/perf_events_test.cpp index 94d1933116207b5e5b9887bb06897af6045b7e89..076a9d68bcc033e036114edda0b55e578ab09d58 100644 --- a/test/unittest/common/native/perf_events_test.cpp +++ b/test/unittest/common/native/perf_events_test.cpp @@ -523,6 +523,40 @@ HWTEST_F(PerfEventsTest, OutputTracking, TestSize.Level1) EXPECT_EQ(event.outputEndTime_, TIME); EXPECT_EQ(event.outputTracking_, true); } + +HWTEST_F(PerfEventsTest, SetConfig, TestSize.Level1) +{ + constexpr uint64_t config = 0x700010007; + constexpr uint64_t config1 = 8; + constexpr uint64_t config2 = 10; + PerfEvents event; + std::map speOptMap = { + {"branch_filter", 1}, {"load_filter", 1}, + {"store_filter", 1}, {"ts_enable", 1}, + {"pa_enable", 1}, {"jitter", 1}, + {"min_latency", config2}, {"event_filter", config1}, + {"pct_enable", 1}, + }; + event.SetConfig(speOptMap); + EXPECT_EQ(event.config_, config); + EXPECT_EQ(event.config1_, config1); + EXPECT_EQ(event.config2_, config2); +} + +HWTEST_F(PerfEventsTest, SetConfig1, TestSize.Level1) +{ + constexpr uint64_t config = 0x700010003; + PerfEvents event; + std::map speOptMap = { + {"branch_filter", 1}, {"load_filter", 1}, + {"store_filter", 1}, {"ts_enable", 1}, + {"pa_enable", 1}, {"jitter", 1}, + {"min_latency", 0}, {"event_filter", 0}, + {"pct_enable", 0}, + }; + event.SetConfig(speOptMap); + EXPECT_EQ(event.config_, config); +} } // namespace HiPerf } // namespace Developtools } // namespace OHOS diff --git a/test/unittest/common/native/perf_file_writer_test.cpp b/test/unittest/common/native/perf_file_writer_test.cpp index 35eea9c6a3e97836e01f7b806afb818de886f605..3b4b3b2d39f152b8ae9e19883ecbe24d64c9cf10 100644 --- a/test/unittest/common/native/perf_file_writer_test.cpp +++ b/test/unittest/common/native/perf_file_writer_test.cpp @@ -137,6 +137,45 @@ HWTEST_F(PerfFileWriterTest, TestFileWriter_Compress, TestSize.Level1) ASSERT_TRUE((access(filename.c_str(), F_OK) != 0)); } +HWTEST_F(PerfFileWriterTest, TestFileWriter_AuxTraceInfo, TestSize.Level1) +{ + std::string filename = "./TestFileWriter_AuxTraceInfo"; + PerfFileWriter fileWriter; + ASSERT_TRUE(fileWriter.Open(filename)) << "current path no write permission?"; + + std::vector attrIds; + AttrWithId attrId; + perf_event_attr attr; + attrId.attr = attr; + attrId.ids.emplace_back(0); + attrIds.emplace_back(attrId); + uint64_t dataSize = 0; + ASSERT_TRUE(fileWriter.WriteAttrAndId(attrIds, true)); + dataSize = dataSize + sizeof(perf_event_header) + sizeof(PerfRecordTtimeConvData) + + sizeof(perf_event_header) + sizeof(PerfRecordAuxtraceInfoData) + + sizeof(perf_event_header) + sizeof(PerfRecordCpuMapData); + + for (uint i = 0; i < TESTRECORDCOUNT; i++) { + std::string testStr = "testFeature " + std::to_string(i); + PerfRecordMmap recordmmap(true, i, i, i, i, i, testStr); + dataSize += recordmmap.GetSize(); + ASSERT_TRUE(fileWriter.WriteRecord(recordmmap)); + ASSERT_TRUE(fileWriter.AddStringFeature(FEATURE::RESERVED, testStr)); + ASSERT_TRUE(fileWriter.AddNrCpusFeature(FEATURE::RESERVED, 0, TESTNUMBER1)); + ASSERT_TRUE(fileWriter.AddU64Feature(FEATURE::RESERVED, TESTNUMBER2)); + std::vector eventDesces; + TestEventDescInit(eventDesces); + ASSERT_TRUE(fileWriter.AddEventDescFeature(FEATURE::RESERVED, eventDesces)); + VirtualRuntime vr; + ASSERT_TRUE(fileWriter.AddSymbolsFeature(vr.GetSymbolsFiles())); + } + ASSERT_EQ(fileWriter.GetDataSize(), dataSize); + ASSERT_EQ(fileWriter.GetRecordCount(), TESTRECORDCOUNT); + ASSERT_TRUE(fileWriter.Close()); + // check file + ASSERT_TRUE((access(filename.c_str(), F_OK) == 0)); +} + HWTEST_F(PerfFileWriterTest, TestFileWriter_NoWriteAttrAndId, TestSize.Level1) { std::string filename = "./TestFileWriter_NoWriteAttrAndId"; diff --git a/test/unittest/common/native/subcommand_record_test.cpp b/test/unittest/common/native/subcommand_record_test.cpp index 0a198618b869d72b07f14c1ea3f64d4ca852ba34..bc53a8c5741342c886d69f8b5472f1dbc02af77d 100644 --- a/test/unittest/common/native/subcommand_record_test.cpp +++ b/test/unittest/common/native/subcommand_record_test.cpp @@ -1891,6 +1891,43 @@ HWTEST_F(SubCommandRecordTest, CheckBacktrackOption, TestSize.Level1) record.clockId_ = "boottime"; EXPECT_EQ(record.CheckBacktrackOption(), true); } + +/** + * @tc.name: CheckSpeOption + * @tc.desc: Test CheckSpeOption + * @tc.type: FUNC + */ +HWTEST_F(SubCommandRecordTest, CheckSpeOption, TestSize.Level1) +{ + constexpr uint64_t disable = 0; + constexpr uint64_t enable = 1; + SubCommandRecord command; + command.speOptMap_["ts_enable"] = enable; // 2 : invalid value + command.speOptMap_["pa_enable"] = enable; + command.speOptMap_["pct_enable"] = enable; + command.speOptMap_["branch_filter"] = enable; + command.speOptMap_["load_filter"] = disable; + command.speOptMap_["store_filter"] = enable; + command.speOptMap_["jitter"] = enable; + EXPECT_EQ(command.CheckSpeOption(), true); +} + +/** + * @tc.name: CheckSpeOptionErr + * @tc.desc: Test CheckSpeOption + * @tc.type: FUNC + */ +HWTEST_F(SubCommandRecordTest, CheckSpeOptionErr, TestSize.Level1) +{ + constexpr uint64_t disable = 0; + constexpr uint64_t enable = 1; + constexpr uint64_t invalid = 20; + SubCommandRecord command; + command.speOptMap_["branch_filter"] = invalid; + command.speOptMap_["load_filter"] = disable; + command.speOptMap_["jitter"] = enable; + EXPECT_EQ(command.CheckSpeOption(), false); +} } // namespace HiPerf } // namespace Developtools } // namespace OHOS