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