• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "perf_event_record_test.h"
17 
18 #include <cstring>
19 
20 using namespace testing::ext;
21 using namespace std;
22 using namespace OHOS::HiviewDFX;
23 
24 namespace OHOS {
25 namespace Developtools {
26 namespace HiPerf {
27 class PerfEventRecordTest : public testing::Test {
28 public:
29     static void SetUpTestCase(void);
30     static void TearDownTestCase(void);
31     void SetUp();
32     void TearDown();
33 
34     static constexpr size_t HEADER_SIZE = sizeof(perf_event_header);
35 };
36 
SetUpTestCase()37 void PerfEventRecordTest::SetUpTestCase() {}
38 
TearDownTestCase()39 void PerfEventRecordTest::TearDownTestCase() {}
40 
SetUp()41 void PerfEventRecordTest::SetUp() {}
42 
TearDown()43 void PerfEventRecordTest::TearDown() {}
44 
CompareByteStream(const uint8_t * a,const uint8_t * b,size_t size)45 static int CompareByteStream(const uint8_t *a, const uint8_t *b, size_t size)
46 {
47     for (size_t i = 0; i < size; i++) {
48         if (a[i] > b[i]) {
49             return (a[i] - b[i]);
50         } else if (a[i] < b[i]) {
51             return (int(a[i]) - int(b[i]));
52         }
53     }
54     return 0;
55 }
56 
57 /**
58  * @tc.name: Test
59  * @tc.desc:
60  * @tc.type: FUNC
61  */
62 const std::string RECORDNAME_MMAP = "mmap";
63 HWTEST_F(PerfEventRecordTest, Mmap, TestSize.Level1)
64 {
65     PerfRecordMmapData data {1, 2, 3, 4, 5, "testdatammap"};
66     PerfRecordMmap recordIn {true,     data.pid,   data.tid,     data.addr,
67                              data.len, data.pgoff, data.filename};
68 
69     ASSERT_EQ(recordIn.GetType(), PERF_RECORD_MMAP);
70     ASSERT_EQ(recordIn.GetName(), RECORDNAME_MMAP);
71     ASSERT_EQ(recordIn.GetMisc(), PERF_RECORD_MISC_KERNEL);
72     ASSERT_EQ(recordIn.GetHeaderSize(), HEADER_SIZE);
73 
74     std::vector<uint8_t> header;
75     recordIn.GetHeaderBinary(header);
76     std::vector<uint8_t> buff;
77     ASSERT_TRUE(recordIn.GetBinary(buff));
78     ASSERT_EQ(CompareByteStream(header.data(), buff.data(), HEADER_SIZE), 0);
79 
80     size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmapData) - KILO + strlen(data.filename) + 1;
81     ASSERT_EQ(recordIn.GetSize(), buffSize);
82 
83     PerfRecordMmap recordOut(buff.data());
84     ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP);
85     ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP);
86     ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
87     ASSERT_EQ(recordOut.GetHeaderSize(), HEADER_SIZE);
88     ASSERT_EQ(recordOut.GetSize(), buffSize);
89     ASSERT_EQ(recordOut.data_.pid, data.pid);
90     ASSERT_EQ(recordOut.data_.tid, data.tid);
91     ASSERT_EQ(recordOut.data_.addr, data.addr);
92     ASSERT_EQ(recordOut.data_.len, data.len);
93     ASSERT_EQ(recordOut.data_.pgoff, data.pgoff);
94     ASSERT_EQ(strcmp(recordOut.data_.filename, data.filename), 0);
95 }
96 
97 const std::string RECORDNAME_MMAP2 = "mmap2";
98 HWTEST_F(PerfEventRecordTest, Mmap2, TestSize.Level1)
99 {
100     PerfRecordMmap2Data data {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, "testdatammap2"};
101     PerfRecordMmap2 recordIn {true,     data.pid, data.tid, data.addr, data.len,   data.pgoff,
102                               data.maj, data.min, data.ino, data.prot, data.flags, data.filename};
103 
104     ASSERT_EQ(recordIn.GetType(), PERF_RECORD_MMAP2);
105     ASSERT_EQ(recordIn.GetName(), RECORDNAME_MMAP2);
106     ASSERT_EQ(recordIn.GetMisc(), PERF_RECORD_MISC_KERNEL);
107     ASSERT_EQ(recordIn.GetHeaderSize(), HEADER_SIZE);
108 
109     std::vector<uint8_t> header;
110     recordIn.GetHeaderBinary(header);
111     std::vector<uint8_t> buff;
112     ASSERT_TRUE(recordIn.GetBinary(buff));
113     ASSERT_EQ(CompareByteStream(header.data(), buff.data(), HEADER_SIZE), 0);
114 
115     size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmap2Data) - KILO + strlen(data.filename) + 1;
116     ASSERT_EQ(recordIn.GetSize(), buffSize);
117 
118     PerfRecordMmap2 recordOut(buff.data());
119     ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP2);
120     ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP2);
121     ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
122     ASSERT_EQ(recordOut.GetHeaderSize(), HEADER_SIZE);
123     ASSERT_EQ(recordOut.GetSize(), buffSize);
124     ASSERT_EQ(recordOut.data_.pid, data.pid);
125     ASSERT_EQ(recordOut.data_.tid, data.tid);
126     ASSERT_EQ(recordOut.data_.addr, data.addr);
127     ASSERT_EQ(recordOut.data_.len, data.len);
128     ASSERT_EQ(recordOut.data_.pgoff, data.pgoff);
129     ASSERT_EQ(recordOut.data_.maj, data.maj);
130     ASSERT_EQ(recordOut.data_.min, data.min);
131     ASSERT_EQ(recordOut.data_.ino, data.ino);
132     ASSERT_EQ(recordOut.data_.prot, data.prot);
133     ASSERT_EQ(recordOut.data_.flags, data.flags);
134     ASSERT_EQ(strcmp(recordOut.data_.filename, data.filename), 0);
135 }
136 
137 const std::string RECORDNAME_COMM = "comm";
138 HWTEST_F(PerfEventRecordTest, Comm, TestSize.Level1)
139 {
140     PerfRecordCommData data {1, 2, "testdatcomm"};
141     PerfRecordComm recordIn {true, data.pid, data.tid, data.comm};
142 
143     ASSERT_EQ(recordIn.GetType(), PERF_RECORD_COMM);
144     ASSERT_EQ(recordIn.GetName(), RECORDNAME_COMM);
145     ASSERT_EQ(recordIn.GetMisc(), PERF_RECORD_MISC_KERNEL);
146     ASSERT_EQ(recordIn.GetHeaderSize(), HEADER_SIZE);
147 
148     std::vector<uint8_t> header;
149     recordIn.GetHeaderBinary(header);
150     std::vector<uint8_t> buff;
151     ASSERT_TRUE(recordIn.GetBinary(buff));
152     ASSERT_EQ(CompareByteStream(header.data(), buff.data(), HEADER_SIZE), 0);
153 
154     size_t buffSize = HEADER_SIZE + sizeof(PerfRecordCommData) - KILO + strlen(data.comm) + 1;
155     ASSERT_EQ(recordIn.GetSize(), buffSize);
156     PerfRecordComm recordOut(buff.data());
157     ASSERT_EQ(recordOut.GetType(), PERF_RECORD_COMM);
158     ASSERT_EQ(recordOut.GetName(), RECORDNAME_COMM);
159     ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
160     ASSERT_EQ(recordOut.GetHeaderSize(), HEADER_SIZE);
161     ASSERT_EQ(recordOut.GetSize(), buffSize);
162     ASSERT_EQ(recordOut.data_.pid, data.pid);
163     ASSERT_EQ(recordOut.data_.tid, data.tid);
164     ASSERT_EQ(strcmp(recordOut.data_.comm, data.comm), 0);
165 }
166 
167 const std::string RECORDNAME_LOST = "lost";
168 HWTEST_F(PerfEventRecordTest, Lost, TestSize.Level1)
169 {
170     struct TestRecordLostst {
171         perf_event_header h;
172         PerfRecordLostData d;
173     };
174     TestRecordLostst data = {
175         {PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordLostst)},
176         {1, 2}};
177 
178     PerfRecordLost record((uint8_t *)&data);
179     ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
180     ASSERT_EQ(record.GetName(), RECORDNAME_LOST);
181     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
182     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
183     ASSERT_EQ(record.GetSize(), sizeof(data));
184 
185     std::vector<uint8_t> buff;
186     ASSERT_TRUE(record.GetBinary(buff));
187     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
188 }
189 
190 const std::string RECORDNAME_EXIT = "exit";
191 HWTEST_F(PerfEventRecordTest, Exit, TestSize.Level1)
192 {
193     struct TestRecordExitst {
194         perf_event_header h;
195         PerfRecordExitData d;
196     };
197     TestRecordExitst data = {{PERF_RECORD_EXIT, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordExitst)},
198                              {1, 2, 3, 4, 5}};
199 
200     PerfRecordExit record((uint8_t *)&data);
201     ASSERT_EQ(record.GetType(), PERF_RECORD_EXIT);
202     ASSERT_EQ(record.GetName(), RECORDNAME_EXIT);
203     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
204     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
205     ASSERT_EQ(record.GetSize(), sizeof(data));
206 
207     std::vector<uint8_t> buff;
208     ASSERT_TRUE(record.GetBinary(buff));
209     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
210 }
211 
212 const std::string RECORDNAME_THROTTLE = "throttle";
213 HWTEST_F(PerfEventRecordTest, Throttle, TestSize.Level1)
214 {
215     struct TestRecordThrottlest {
216         perf_event_header h;
217         PerfRecordThrottleData d;
218     };
219     TestRecordThrottlest data = {
220         {PERF_RECORD_THROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordThrottlest)},
221         {1, 2, 3}};
222 
223     PerfRecordThrottle record((uint8_t *)&data);
224     ASSERT_EQ(record.GetType(), PERF_RECORD_THROTTLE);
225     ASSERT_EQ(record.GetName(), RECORDNAME_THROTTLE);
226     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
227     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
228     ASSERT_EQ(record.GetSize(), sizeof(data));
229 
230     std::vector<uint8_t> buff;
231     ASSERT_TRUE(record.GetBinary(buff));
232     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
233 }
234 
235 const std::string RECORDNAME_UNTHROTTLE = "unthrottle";
236 HWTEST_F(PerfEventRecordTest, Unthrottle, TestSize.Level1)
237 {
238     struct TestRecordUNThrottlest {
239         perf_event_header h;
240         PerfRecordThrottleData d;
241     };
242     TestRecordUNThrottlest data = {
243         {PERF_RECORD_UNTHROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordUNThrottlest)},
244         {1, 2, 3}};
245 
246     PerfRecordUnthrottle record((uint8_t *)&data);
247     ASSERT_EQ(record.GetType(), PERF_RECORD_UNTHROTTLE);
248     ASSERT_EQ(record.GetName(), RECORDNAME_UNTHROTTLE);
249     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
250     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
251     ASSERT_EQ(record.GetSize(), sizeof(data));
252 
253     std::vector<uint8_t> buff;
254     ASSERT_TRUE(record.GetBinary(buff));
255     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
256 }
257 
258 const std::string RECORDNAME_FORK = "fork";
259 HWTEST_F(PerfEventRecordTest, Fork, TestSize.Level1)
260 {
261     struct TestRecordForkst {
262         perf_event_header h;
263         PerfRecordForkData d;
264     };
265     TestRecordForkst data = {{PERF_RECORD_FORK, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordForkst)},
266                              {1, 2, 3, 4, 5}};
267 
268     PerfRecordFork record((uint8_t *)&data);
269     ASSERT_EQ(record.GetType(), PERF_RECORD_FORK);
270     ASSERT_EQ(record.GetName(), RECORDNAME_FORK);
271     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
272     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
273     ASSERT_EQ(record.GetSize(), sizeof(data));
274 
275     std::vector<uint8_t> buff;
276     ASSERT_TRUE(record.GetBinary(buff));
277     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
278 }
279 
280 struct TestRecordSamplest {
281     perf_event_header header_;
282     PerfRecordSampleData data_;
283 };
284 
InitTestRecordSample(TestRecordSamplest & record)285 static void InitTestRecordSample(TestRecordSamplest &record)
286 {
287     record.header_.size = sizeof(perf_event_header);
288     record.header_.size +=
289         sizeof(record.data_.sample_id) + sizeof(record.data_.sample_id) + sizeof(record.data_.ip) +
290         sizeof(record.data_.pid) + sizeof(record.data_.tid) + sizeof(record.data_.time) +
291         sizeof(record.data_.addr) + sizeof(record.data_.id) + sizeof(record.data_.stream_id) +
292         sizeof(record.data_.cpu) + sizeof(record.data_.res) + sizeof(record.data_.period);
293 
294     // v??
295 
296     record.data_.nr = 0;
297     record.data_.ips = nullptr;
298     record.header_.size += sizeof(record.data_.nr);
299     record.data_.raw_size = 0;
300     record.data_.raw_data = nullptr;
301     record.header_.size += sizeof(record.data_.raw_size);
302     record.data_.bnr = 0;
303     record.data_.lbr = nullptr;
304     record.header_.size += sizeof(record.data_.bnr);
305     record.data_.user_abi = 0;
306     record.data_.reg_mask = 0;
307     record.header_.size += sizeof(record.data_.user_abi);
308     record.data_.stack_size = 0;
309     record.header_.size += sizeof(record.data_.stack_size);
310     // others
311 }
312 
CompareRecordSample50(const TestRecordSamplest & record,const std::vector<u8> & buf,size_t offset)313 static bool CompareRecordSample50(const TestRecordSamplest &record, const std::vector<u8> &buf,
314                                   size_t offset)
315 {
316     const uint8_t *p = buf.data() + offset;
317 
318     if (record.data_.nr != *(reinterpret_cast<const u64 *>(p))) {
319         return false;
320     }
321     p += sizeof(u64);
322 
323     if (record.data_.raw_size != *(reinterpret_cast<const u32 *>(p))) {
324         return false;
325     }
326     p += sizeof(u32);
327 
328     if (record.data_.bnr != *(reinterpret_cast<const u64 *>(p))) {
329         return false;
330     }
331     p += sizeof(u64);
332 
333     if (record.data_.user_abi != *(reinterpret_cast<const u64 *>(p))) {
334         return false;
335     }
336     p += sizeof(u64);
337 
338     if (record.data_.stack_size != *(reinterpret_cast<const u64 *>(p))) {
339         return false;
340     }
341     p += sizeof(u64);
342 
343     return true;
344 }
345 
CompareRecordSample(const TestRecordSamplest & record,const std::vector<u8> & buf)346 static bool CompareRecordSample(const TestRecordSamplest &record, const std::vector<u8> &buf)
347 {
348     if (buf.size() < record.header_.size) {
349         return false;
350     }
351     const uint8_t *p = buf.data();
352     p += sizeof(perf_event_header);
353 
354     if (record.data_.sample_id != *(reinterpret_cast<const u64 *>(p))) {
355         return false;
356     }
357     p += sizeof(u64);
358 
359     if (record.data_.ip != *(reinterpret_cast<const u64 *>(p))) {
360         return false;
361     }
362     p += sizeof(u64);
363 
364     if (record.data_.pid != *(reinterpret_cast<const u32 *>(p))) {
365         return false;
366     }
367     p += sizeof(u32);
368 
369     if (record.data_.tid != *(reinterpret_cast<const u32 *>(p))) {
370         return false;
371     }
372     p += sizeof(u32);
373 
374     if (record.data_.time != *(reinterpret_cast<const u64 *>(p))) {
375         return false;
376     }
377     p += sizeof(u64);
378 
379     if (record.data_.addr != *(reinterpret_cast<const u64 *>(p))) {
380         return false;
381     }
382     p += sizeof(u64);
383 
384     if (record.data_.id != *(reinterpret_cast<const u64 *>(p))) {
385         return false;
386     }
387     p += sizeof(u64);
388 
389     if (record.data_.stream_id != *(reinterpret_cast<const u64 *>(p))) {
390         return false;
391     }
392     p += sizeof(u64);
393 
394     if (record.data_.cpu != *(reinterpret_cast<const u32 *>(p))) {
395         return false;
396     }
397     p += sizeof(u32);
398 
399     if (record.data_.res != *(reinterpret_cast<const u32 *>(p))) {
400         return false;
401     }
402     p += sizeof(u32);
403 
404     if (record.data_.period != *(reinterpret_cast<const u64 *>(p))) {
405         return false;
406     }
407     p += sizeof(u64);
408 
409     return CompareRecordSample50(record, buf, p - buf.data());
410 }
411 
412 const std::string RECORDNAME_SAMPLE = "sample";
413 HWTEST_F(PerfEventRecordTest, Sample, TestSize.Level1)
414 {
415     perf_event_attr attr {};
416     attr.sample_type = UINT64_MAX;
417     TestRecordSamplest data = {
418         {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
419         {}};
420     InitTestRecordSample(data);
421 
422     PerfRecordSample record((uint8_t *)&data, attr);
423     ASSERT_EQ(record.GetType(), PERF_RECORD_SAMPLE);
424     ASSERT_EQ(record.GetName(), RECORDNAME_SAMPLE);
425     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
426     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
427 
428     std::vector<uint8_t> buff;
429     ASSERT_TRUE(record.GetBinary(buff));
430     ASSERT_TRUE(CompareRecordSample(data, buff));
431 }
432 
433 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack1, TestSize.Level1)
434 {
435     perf_event_attr attr {};
436     attr.sample_type = UINT64_MAX;
437     TestRecordSamplest data = {
438         {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
439         {}};
440     InitTestRecordSample(data);
441 
442     PerfRecordSample record((uint8_t *)&data, attr);
443     record.sampleType_ |= PERF_SAMPLE_REGS_USER;
444     record.sampleType_ |= PERF_SAMPLE_STACK_USER;
445     record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
446 
447     std::vector<u64> ips = {};
448     record.data_.ips = ips.data();
449     record.data_.nr = ips.size();
450     record.callFrames_ = {1, 2, 3, 4, 5, 6, 7, 8, 9};
451     record.ReplaceWithCallStack();
452     ASSERT_EQ(record.data_.reg_nr, 0u);
453     ASSERT_EQ(record.data_.user_abi, 0u);
454     ASSERT_EQ(record.data_.stack_size, 0u);
455     ASSERT_EQ(record.data_.dyn_size, 0u);
456 
457     // include PERF_CONTEXT_USER
458     ASSERT_EQ(record.callFrames_.size() + 1, record.data_.nr);
459     ASSERT_EQ(record.data_.ips[0], PERF_CONTEXT_USER);
460     for (size_t i = 1; i < record.data_.nr; i++) {
461         ASSERT_EQ(record.data_.ips[i], record.callFrames_.at(i - 1).ip_);
462     }
463     // result is 1 - 9
464 }
465 
466 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack2, TestSize.Level1)
467 {
468     perf_event_attr attr {};
469     attr.sample_type = UINT64_MAX;
470     TestRecordSamplest data = {
471         {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
472         {}};
473     InitTestRecordSample(data);
474 
475     PerfRecordSample record((uint8_t *)&data, attr);
476     record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
477 
478     std::vector<u64> ips = {};
479     record.data_.ips = ips.data();
480     record.data_.nr = ips.size();
481     record.callFrames_ = {1, 2, 3, 4, 5, 6, 7, 8, 9};
482     record.ReplaceWithCallStack();
483     // include PERF_CONTEXT_USER
484     ASSERT_EQ(record.callFrames_.size() + 1, record.data_.nr);
485     ASSERT_EQ(record.data_.ips[0], PERF_CONTEXT_USER);
486     for (size_t i = 1; i < record.data_.nr; i++) {
487         ASSERT_EQ(record.data_.ips[i], record.callFrames_.at(i - 1).ip_);
488     }
489     // result is 1 - 9
490 }
491 
492 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack3, TestSize.Level1)
493 {
494     perf_event_attr attr {};
495     attr.sample_type = UINT64_MAX;
496     TestRecordSamplest data = {
497         {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
498         {}};
499     InitTestRecordSample(data);
500 
501     PerfRecordSample record((uint8_t *)&data, attr);
502     record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
503 
504     record.callFrames_ = {4, 5, 6, 7, 8, 9};
505     std::vector<u64> ips = {0, 1, 2, 3};
506     record.data_.ips = ips.data();
507     record.data_.nr = ips.size();
508     record.ReplaceWithCallStack();
509     // include PERF_CONTEXT_USER
510     ASSERT_EQ(record.callFrames_.size() + ips.size() + 1, record.data_.nr);
511     for (size_t i = 0; i < ips.size(); i++) {
512         ASSERT_EQ(record.data_.ips[i], ips[i]);
513     }
514     ASSERT_EQ(record.data_.ips[ips.size()], PERF_CONTEXT_USER);
515     for (size_t i = 0; i < record.callFrames_.size(); i++) {
516         ASSERT_EQ(record.data_.ips[i + ips.size() + 1], record.callFrames_.at(i).ip_);
517     }
518     // result is 0 - 3 , PERF_CONTEXT_USER , 4 - 9
519 }
520 
521 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack4, TestSize.Level1)
522 {
523     perf_event_attr attr {};
524     attr.sample_type = UINT64_MAX;
525     TestRecordSamplest data = {
526         {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
527         {}};
528     InitTestRecordSample(data);
529 
530     PerfRecordSample record((uint8_t *)&data, attr);
531     record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
532 
533     record.callFrames_ = {};
534     std::vector<u64> ips = {0, 1, 2, 3};
535     record.data_.ips = ips.data();
536     record.data_.nr = ips.size();
537     record.ReplaceWithCallStack();
538     // not PERF_CONTEXT_USER will add
539     ASSERT_EQ(ips.size(), record.data_.nr);
540     for (size_t i = 0; i < record.data_.nr; i++) {
541         ASSERT_EQ(record.data_.ips[i], ips[i]);
542     }
543     // result is 0 - 3
544 }
545 
546 const std::string RECORDNAME_READ = "read";
547 HWTEST_F(PerfEventRecordTest, Read, TestSize.Level1)
548 {
549     struct PerfRecordReadst {
550         perf_event_header h;
551         PerfRecordReadData d;
552     };
553     PerfRecordReadst data = {{PERF_RECORD_READ, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordReadst)},
554                              {1, 2, {11, 12, 13, 14}}};
555 
556     PerfRecordRead record((uint8_t *)&data);
557     ASSERT_EQ(record.GetType(), PERF_RECORD_READ);
558     ASSERT_EQ(record.GetName(), RECORDNAME_READ);
559     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
560     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
561     ASSERT_EQ(record.GetSize(), sizeof(data));
562 
563     std::vector<uint8_t> buff;
564     ASSERT_TRUE(record.GetBinary(buff));
565     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
566 }
567 
568 const std::string RECORDNAME_AUX = "aux";
569 HWTEST_F(PerfEventRecordTest, Aux, TestSize.Level1)
570 {
571     struct PerfRecordAuxst {
572         perf_event_header h;
573         PerfRecordAuxData d;
574     };
575     PerfRecordAuxst data = {{PERF_RECORD_AUX, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordAuxst)},
576                             {1, 2, 3}};
577 
578     PerfRecordAux record((uint8_t *)&data);
579     ASSERT_EQ(record.GetType(), PERF_RECORD_AUX);
580     ASSERT_EQ(record.GetName(), RECORDNAME_AUX);
581     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
582     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
583     ASSERT_EQ(record.GetSize(), sizeof(data));
584 
585     std::vector<uint8_t> buff;
586     ASSERT_TRUE(record.GetBinary(buff));
587     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
588 }
589 
590 const std::string RECORDNAME_ITRACE_START = "itraceStart";
591 HWTEST_F(PerfEventRecordTest, ItraceStart, TestSize.Level1)
592 {
593     struct PerfRecordItraceStartst {
594         perf_event_header h;
595         PerfRecordItraceStartData d;
596     };
597     PerfRecordItraceStartst data = {
598         {PERF_RECORD_ITRACE_START, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordItraceStartst)},
599         {1, 2}};
600 
601     PerfRecordItraceStart record((uint8_t *)&data);
602     ASSERT_EQ(record.GetType(), PERF_RECORD_ITRACE_START);
603     ASSERT_EQ(record.GetName(), RECORDNAME_ITRACE_START);
604     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
605     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
606     ASSERT_EQ(record.GetSize(), sizeof(data));
607 
608     std::vector<uint8_t> buff;
609     ASSERT_TRUE(record.GetBinary(buff));
610     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
611 }
612 
613 const std::string RECORDNAME_LOST_SAMPLES = "lostSamples";
614 HWTEST_F(PerfEventRecordTest, LostSamples, TestSize.Level1)
615 {
616     struct PerfRecordLostSamplesst {
617         perf_event_header h;
618         PerfRecordLostSamplesData d;
619     };
620     PerfRecordLostSamplesst data = {
621         {PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordLostSamplesst)},
622         {1}};
623 
624     PerfRecordLostSamples record((uint8_t *)&data);
625     ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
626     ASSERT_EQ(record.GetName(), RECORDNAME_LOST_SAMPLES);
627     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
628     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
629     ASSERT_EQ(record.GetSize(), sizeof(data));
630 
631     std::vector<uint8_t> buff;
632     ASSERT_TRUE(record.GetBinary(buff));
633     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
634 }
635 
636 const std::string RECORDNAME_SWITCH = "switch";
637 HWTEST_F(PerfEventRecordTest, Switch, TestSize.Level1)
638 {
639     struct PerfRecordSwitchst {
640         perf_event_header h;
641         PerfRecordSwitchData d;
642     };
643     PerfRecordSwitchst data = {
644         {PERF_RECORD_SWITCH, PERF_RECORD_MISC_KERNEL, sizeof(perf_event_header)},
645         {}};
646 
647     PerfRecordSwitch record((uint8_t *)&data);
648     ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH);
649     ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH);
650     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
651     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
652     ASSERT_EQ(record.GetSize(), HEADER_SIZE);
653 
654     std::vector<uint8_t> buff;
655     ASSERT_TRUE(record.GetBinary(buff));
656     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), HEADER_SIZE), 0);
657 }
658 
659 const std::string RECORDNAME_SWITCH_CPU_WIDE = "switchCpuWide";
660 HWTEST_F(PerfEventRecordTest, SwitchCpuWide, TestSize.Level1)
661 {
662     struct PerfRecordSwitchCpuWidest {
663         perf_event_header h;
664         PerfRecordSwitchCpuWideData d;
665     };
666     PerfRecordSwitchCpuWidest data = {
667         {PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
668         {}};
669 
670     PerfRecordSwitchCpuWide record((uint8_t *)&data);
671     ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH_CPU_WIDE);
672     ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH_CPU_WIDE);
673     ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
674     ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
675     ASSERT_EQ(record.GetSize(), sizeof(data));
676 
677     std::vector<uint8_t> buff;
678     ASSERT_TRUE(record.GetBinary(buff));
679     ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
680 }
681 } // namespace HiPerf
682 } // namespace Developtools
683 } // namespace OHOS
684