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 #include <thread>
20
21 using namespace testing::ext;
22
23 namespace OHOS {
24 namespace Developtools {
25 namespace HiPerf {
26 class PerfEventRecordTest : public testing::Test {
27 public:
28 static void SetUpTestCase(void);
29 static void TearDownTestCase(void);
30 void SetUp();
31 void TearDown();
32
33 static constexpr size_t HEADER_SIZE = sizeof(perf_event_header);
34 };
35
SetUpTestCase()36 void PerfEventRecordTest::SetUpTestCase() {}
37
TearDownTestCase()38 void PerfEventRecordTest::TearDownTestCase() {}
39
SetUp()40 void PerfEventRecordTest::SetUp() {}
41
TearDown()42 void PerfEventRecordTest::TearDown() {}
43
CompareByteStream(const uint8_t * a,const uint8_t * b,size_t size)44 static int CompareByteStream(const uint8_t *a, const uint8_t *b, size_t size)
45 {
46 for (size_t i = 0; i < size; i++) {
47 if (a[i] > b[i]) {
48 return (a[i] - b[i]);
49 } else if (a[i] < b[i]) {
50 return (int(a[i]) - int(b[i]));
51 }
52 }
53 return 0;
54 }
55
56 /**
57 * @tc.name: Test
58 * @tc.desc:
59 * @tc.type: FUNC
60 */
61 const std::string RECORDNAME_MMAP = "mmap";
62 HWTEST_F(PerfEventRecordTest, Mmap, TestSize.Level1)
63 {
64 PerfRecordMmapData data {1, 2, 3, 4, 5, "testdatammap"};
65 PerfRecordMmap recordIn {true, data.pid, data.tid, data.addr,
66 data.len, data.pgoff, data.filename};
67
68 ASSERT_EQ(recordIn.GetType(), PERF_RECORD_MMAP);
69 ASSERT_EQ(recordIn.GetName(), RECORDNAME_MMAP);
70 ASSERT_EQ(recordIn.GetMisc(), PERF_RECORD_MISC_KERNEL);
71 ASSERT_EQ(recordIn.GetHeaderSize(), HEADER_SIZE);
72
73 std::vector<uint8_t> header;
74 recordIn.GetHeaderBinary(header);
75 std::vector<uint8_t> buff;
76 ASSERT_TRUE(recordIn.GetBinary(buff));
77 ASSERT_EQ(CompareByteStream(header.data(), buff.data(), HEADER_SIZE), 0);
78
79 size_t buffSize = HEADER_SIZE + sizeof(PerfRecordMmapData) - KILO + strlen(data.filename) + 1;
80 ASSERT_EQ(recordIn.GetSize(), buffSize);
81
82 PerfRecordMmap recordOut;
83 recordOut.Init(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;
119 recordOut.Init(buff.data());
120 ASSERT_EQ(recordOut.GetType(), PERF_RECORD_MMAP2);
121 ASSERT_EQ(recordOut.GetName(), RECORDNAME_MMAP2);
122 ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
123 ASSERT_EQ(recordOut.GetHeaderSize(), HEADER_SIZE);
124 ASSERT_EQ(recordOut.GetSize(), buffSize);
125 ASSERT_EQ(recordOut.data_.pid, data.pid);
126 ASSERT_EQ(recordOut.data_.tid, data.tid);
127 ASSERT_EQ(recordOut.data_.addr, data.addr);
128 ASSERT_EQ(recordOut.data_.len, data.len);
129 ASSERT_EQ(recordOut.data_.pgoff, data.pgoff);
130 ASSERT_EQ(recordOut.data_.maj, data.maj);
131 ASSERT_EQ(recordOut.data_.min, data.min);
132 ASSERT_EQ(recordOut.data_.ino, data.ino);
133 ASSERT_EQ(recordOut.data_.prot, data.prot);
134 ASSERT_EQ(recordOut.data_.flags, data.flags);
135 ASSERT_EQ(strcmp(recordOut.data_.filename, data.filename), 0);
136 }
137
138 const std::string RECORDNAME_COMM = "comm";
139 HWTEST_F(PerfEventRecordTest, Comm, TestSize.Level1)
140 {
141 PerfRecordCommData data {1, 2, "testdatcomm"};
142 PerfRecordComm recordIn {true, data.pid, data.tid, data.comm};
143
144 ASSERT_EQ(recordIn.GetType(), PERF_RECORD_COMM);
145 ASSERT_EQ(recordIn.GetName(), RECORDNAME_COMM);
146 ASSERT_EQ(recordIn.GetMisc(), PERF_RECORD_MISC_KERNEL);
147 ASSERT_EQ(recordIn.GetHeaderSize(), HEADER_SIZE);
148
149 std::vector<uint8_t> header;
150 recordIn.GetHeaderBinary(header);
151 std::vector<uint8_t> buff;
152 ASSERT_TRUE(recordIn.GetBinary(buff));
153 ASSERT_EQ(CompareByteStream(header.data(), buff.data(), HEADER_SIZE), 0);
154
155 size_t buffSize = HEADER_SIZE + sizeof(PerfRecordCommData) - KILO + strlen(data.comm) + 1;
156 ASSERT_EQ(recordIn.GetSize(), buffSize);
157 PerfRecordComm recordOut;
158 recordOut.Init(buff.data());
159 ASSERT_EQ(recordOut.GetType(), PERF_RECORD_COMM);
160 ASSERT_EQ(recordOut.GetName(), RECORDNAME_COMM);
161 ASSERT_EQ(recordOut.GetMisc(), PERF_RECORD_MISC_KERNEL);
162 ASSERT_EQ(recordOut.GetHeaderSize(), HEADER_SIZE);
163 ASSERT_EQ(recordOut.GetSize(), buffSize);
164 ASSERT_EQ(recordOut.data_.pid, data.pid);
165 ASSERT_EQ(recordOut.data_.tid, data.tid);
166 ASSERT_EQ(strcmp(recordOut.data_.comm, data.comm), 0);
167 }
168
169 const std::string RECORDNAME_LOST = "lost";
170 HWTEST_F(PerfEventRecordTest, Lost, TestSize.Level1)
171 {
172 struct TestRecordLostst {
173 perf_event_header h;
174 PerfRecordLostData d;
175 };
176 TestRecordLostst data = {
177 {PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordLostst)},
178 {1, 2}};
179
180 PerfRecordLost record;
181 record.Init((uint8_t *)&data);
182 ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
183 ASSERT_EQ(record.GetName(), RECORDNAME_LOST);
184 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
185 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
186 ASSERT_EQ(record.GetSize(), sizeof(data));
187
188 std::vector<uint8_t> buff;
189 ASSERT_TRUE(record.GetBinary(buff));
190 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
191 }
192
193 const std::string RECORDNAME_EXIT = "exit";
194 HWTEST_F(PerfEventRecordTest, Exit, TestSize.Level1)
195 {
196 struct TestRecordExitst {
197 perf_event_header h;
198 PerfRecordExitData d;
199 };
200 TestRecordExitst data = {{PERF_RECORD_EXIT, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordExitst)},
201 {1, 2, 3, 4, 5}};
202
203 PerfRecordExit record;
204 record.Init((uint8_t *)&data);
205 ASSERT_EQ(record.GetType(), PERF_RECORD_EXIT);
206 ASSERT_EQ(record.GetName(), RECORDNAME_EXIT);
207 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
208 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
209 ASSERT_EQ(record.GetSize(), sizeof(data));
210
211 std::vector<uint8_t> buff;
212 ASSERT_TRUE(record.GetBinary(buff));
213 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
214 }
215
216 const std::string RECORDNAME_THROTTLE = "throttle";
217 HWTEST_F(PerfEventRecordTest, Throttle, TestSize.Level1)
218 {
219 struct TestRecordThrottlest {
220 perf_event_header h;
221 PerfRecordThrottleData d;
222 };
223 TestRecordThrottlest data = {
224 {PERF_RECORD_THROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordThrottlest)},
225 {1, 2, 3}};
226
227 PerfRecordThrottle record;
228 record.Init((uint8_t *)&data);
229 ASSERT_EQ(record.GetType(), PERF_RECORD_THROTTLE);
230 ASSERT_EQ(record.GetName(), RECORDNAME_THROTTLE);
231 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
232 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
233 ASSERT_EQ(record.GetSize(), sizeof(data));
234
235 std::vector<uint8_t> buff;
236 ASSERT_TRUE(record.GetBinary(buff));
237 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
238 }
239
240 const std::string RECORDNAME_UNTHROTTLE = "unthrottle";
241 HWTEST_F(PerfEventRecordTest, Unthrottle, TestSize.Level1)
242 {
243 struct TestRecordUNThrottlest {
244 perf_event_header h;
245 PerfRecordThrottleData d;
246 };
247 TestRecordUNThrottlest data = {
248 {PERF_RECORD_UNTHROTTLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordUNThrottlest)},
249 {1, 2, 3}};
250
251 PerfRecordUnthrottle record;
252 record.Init((uint8_t *)&data);
253 ASSERT_EQ(record.GetType(), PERF_RECORD_UNTHROTTLE);
254 ASSERT_EQ(record.GetName(), RECORDNAME_UNTHROTTLE);
255 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
256 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
257 ASSERT_EQ(record.GetSize(), sizeof(data));
258
259 std::vector<uint8_t> buff;
260 ASSERT_TRUE(record.GetBinary(buff));
261 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
262 }
263
264 const std::string RECORDNAME_FORK = "fork";
265 HWTEST_F(PerfEventRecordTest, Fork, TestSize.Level1)
266 {
267 struct TestRecordForkst {
268 perf_event_header h;
269 PerfRecordForkData d;
270 };
271 TestRecordForkst data = {{PERF_RECORD_FORK, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordForkst)},
272 {1, 2, 3, 4, 5}};
273
274 PerfRecordFork record;
275 record.Init((uint8_t *)&data);
276 ASSERT_EQ(record.GetType(), PERF_RECORD_FORK);
277 ASSERT_EQ(record.GetName(), RECORDNAME_FORK);
278 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
279 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
280 ASSERT_EQ(record.GetSize(), sizeof(data));
281
282 std::vector<uint8_t> buff;
283 ASSERT_TRUE(record.GetBinary(buff));
284 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
285 }
286
287 struct TestRecordSamplest {
288 perf_event_header header_;
289 PerfRecordSampleData data_;
290 };
291
InitTestRecordSample(TestRecordSamplest & record)292 static void InitTestRecordSample(TestRecordSamplest &record)
293 {
294 record.header_.size = sizeof(perf_event_header);
295 record.header_.size +=
296 sizeof(record.data_.sample_id) + sizeof(record.data_.sample_id) + sizeof(record.data_.ip) +
297 sizeof(record.data_.pid) + sizeof(record.data_.tid) + sizeof(record.data_.time) +
298 sizeof(record.data_.addr) + sizeof(record.data_.id) + sizeof(record.data_.stream_id) +
299 sizeof(record.data_.cpu) + sizeof(record.data_.res) + sizeof(record.data_.period);
300
301 // v??
302
303 record.data_.nr = 0;
304 record.data_.ips = nullptr;
305 record.header_.size += sizeof(record.data_.nr);
306 record.data_.raw_size = 0;
307 record.data_.raw_data = nullptr;
308 record.header_.size += sizeof(record.data_.raw_size);
309 record.data_.bnr = 0;
310 record.data_.lbr = nullptr;
311 record.header_.size += sizeof(record.data_.bnr);
312 record.data_.user_abi = 0;
313 record.data_.reg_mask = 0;
314 record.header_.size += sizeof(record.data_.user_abi);
315 record.data_.stack_size = 0;
316 record.header_.size += sizeof(record.data_.stack_size);
317 // others
318 }
319
CompareRecordSample50(const TestRecordSamplest & record,const std::vector<u8> & buf,size_t offset)320 static bool CompareRecordSample50(const TestRecordSamplest &record, const std::vector<u8> &buf,
321 size_t offset)
322 {
323 const uint8_t *p = buf.data() + offset;
324
325 if (record.data_.nr != *(reinterpret_cast<const u64 *>(p))) {
326 return false;
327 }
328 p += sizeof(u64);
329
330 if (record.data_.raw_size != *(reinterpret_cast<const u32 *>(p))) {
331 return false;
332 }
333 p += sizeof(u32);
334
335 if (record.data_.bnr != *(reinterpret_cast<const u64 *>(p))) {
336 return false;
337 }
338 p += sizeof(u64);
339
340 if (record.data_.user_abi != *(reinterpret_cast<const u64 *>(p))) {
341 return false;
342 }
343 p += sizeof(u64);
344
345 if (record.data_.stack_size != *(reinterpret_cast<const u64 *>(p))) {
346 return false;
347 }
348 p += sizeof(u64);
349
350 return true;
351 }
352
CompareRecordSample(const TestRecordSamplest & record,const std::vector<u8> & buf)353 static bool CompareRecordSample(const TestRecordSamplest &record, const std::vector<u8> &buf)
354 {
355 if (buf.size() < record.header_.size) {
356 return false;
357 }
358 const uint8_t *p = buf.data();
359 p += sizeof(perf_event_header);
360
361 if (record.data_.sample_id != *(reinterpret_cast<const u64 *>(p))) {
362 return false;
363 }
364 p += sizeof(u64);
365
366 if (record.data_.ip != *(reinterpret_cast<const u64 *>(p))) {
367 return false;
368 }
369 p += sizeof(u64);
370
371 if (record.data_.pid != *(reinterpret_cast<const u32 *>(p))) {
372 return false;
373 }
374 p += sizeof(u32);
375
376 if (record.data_.tid != *(reinterpret_cast<const u32 *>(p))) {
377 return false;
378 }
379 p += sizeof(u32);
380
381 if (record.data_.time != *(reinterpret_cast<const u64 *>(p))) {
382 return false;
383 }
384 p += sizeof(u64);
385
386 if (record.data_.addr != *(reinterpret_cast<const u64 *>(p))) {
387 return false;
388 }
389 p += sizeof(u64);
390
391 if (record.data_.id != *(reinterpret_cast<const u64 *>(p))) {
392 return false;
393 }
394 p += sizeof(u64);
395
396 if (record.data_.stream_id != *(reinterpret_cast<const u64 *>(p))) {
397 return false;
398 }
399 p += sizeof(u64);
400
401 if (record.data_.cpu != *(reinterpret_cast<const u32 *>(p))) {
402 return false;
403 }
404 p += sizeof(u32);
405
406 if (record.data_.res != *(reinterpret_cast<const u32 *>(p))) {
407 return false;
408 }
409 p += sizeof(u32);
410
411 if (record.data_.period != *(reinterpret_cast<const u64 *>(p))) {
412 return false;
413 }
414 p += sizeof(u64);
415
416 return CompareRecordSample50(record, buf, p - buf.data());
417 }
418
419 const std::string RECORDNAME_SAMPLE = "sample";
420 HWTEST_F(PerfEventRecordTest, Sample, TestSize.Level1)
421 {
422 perf_event_attr attr {};
423 attr.sample_type = UINT64_MAX;
424 TestRecordSamplest data = {
425 {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
426 {}};
427 InitTestRecordSample(data);
428
429 PerfRecordSample record;
430 record.Init((uint8_t *)&data, attr);
431 ASSERT_EQ(record.GetType(), PERF_RECORD_SAMPLE);
432 ASSERT_EQ(record.GetName(), RECORDNAME_SAMPLE);
433 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
434 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
435
436 std::vector<uint8_t> buff;
437 ASSERT_TRUE(record.GetBinary(buff));
438 ASSERT_TRUE(CompareRecordSample(data, buff));
439 }
440
441 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack1, TestSize.Level1)
442 {
443 perf_event_attr attr {};
444 attr.sample_type = UINT64_MAX;
445 TestRecordSamplest data = {
446 {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
447 {}};
448 InitTestRecordSample(data);
449
450 PerfRecordSample record;
451 record.Init((uint8_t *)&data, attr);
452 record.sampleType_ |= PERF_SAMPLE_REGS_USER;
453 record.sampleType_ |= PERF_SAMPLE_STACK_USER;
454 record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
455
456 std::vector<u64> ips = {};
457 record.data_.ips = ips.data();
458 record.data_.nr = ips.size();
459 record.callFrames_ = {1, 2, 3, 4, 5, 6, 7, 8, 9};
460 record.ReplaceWithCallStack();
461 ASSERT_EQ(record.data_.reg_nr, 0u);
462 ASSERT_EQ(record.data_.user_abi, 0u);
463 ASSERT_EQ(record.data_.stack_size, 0u);
464 ASSERT_EQ(record.data_.dyn_size, 0u);
465
466 // include PERF_CONTEXT_USER
467 ASSERT_EQ(record.callFrames_.size() + 1, record.data_.nr);
468 ASSERT_EQ(record.data_.ips[0], PERF_CONTEXT_USER);
469 for (size_t i = 1; i < record.data_.nr; i++) {
470 ASSERT_EQ(record.data_.ips[i], record.callFrames_.at(i - 1).pc);
471 }
472 // result is 1 - 9
473 }
474
475 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack2, TestSize.Level1)
476 {
477 perf_event_attr attr {};
478 attr.sample_type = UINT64_MAX;
479 TestRecordSamplest data = {
480 {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
481 {}};
482 InitTestRecordSample(data);
483
484 PerfRecordSample record;
485 record.Init((uint8_t *)&data, attr);
486 record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
487
488 std::vector<u64> ips = {};
489 record.data_.ips = ips.data();
490 record.data_.nr = ips.size();
491 record.callFrames_ = {1, 2, 3, 4, 5, 6, 7, 8, 9};
492 record.ReplaceWithCallStack();
493 // include PERF_CONTEXT_USER
494 ASSERT_EQ(record.callFrames_.size() + 1, record.data_.nr);
495 ASSERT_EQ(record.data_.ips[0], PERF_CONTEXT_USER);
496 for (size_t i = 1; i < record.data_.nr; i++) {
497 ASSERT_EQ(record.data_.ips[i], record.callFrames_.at(i - 1).pc);
498 }
499 // result is 1 - 9
500 }
501
502 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack3, TestSize.Level1)
503 {
504 perf_event_attr attr {};
505 attr.sample_type = UINT64_MAX;
506 TestRecordSamplest data = {
507 {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
508 {}};
509 InitTestRecordSample(data);
510
511 PerfRecordSample record;
512 record.Init((uint8_t *)&data, attr);
513 record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
514
515 record.callFrames_ = {4, 5, 6, 7, 8, 9};
516 std::vector<u64> ips = {0, 1, 2, 3};
517 record.data_.ips = ips.data();
518 record.data_.nr = ips.size();
519 record.ReplaceWithCallStack();
520 // include PERF_CONTEXT_USER
521 ASSERT_EQ(record.callFrames_.size() + ips.size() + 1, record.data_.nr);
522 for (size_t i = 0; i < ips.size(); i++) {
523 ASSERT_EQ(record.data_.ips[i], ips[i]);
524 }
525 ASSERT_EQ(record.data_.ips[ips.size()], PERF_CONTEXT_USER);
526 for (size_t i = 0; i < record.callFrames_.size(); i++) {
527 ASSERT_EQ(record.data_.ips[i + ips.size() + 1], record.callFrames_.at(i).pc);
528 }
529 // result is 0 - 3 , PERF_CONTEXT_USER , 4 - 9
530 }
531
532 HWTEST_F(PerfEventRecordTest, SampleReplaceWithCallStack4, TestSize.Level1)
533 {
534 perf_event_attr attr {};
535 attr.sample_type = UINT64_MAX;
536 TestRecordSamplest data = {
537 {PERF_RECORD_SAMPLE, PERF_RECORD_MISC_KERNEL, sizeof(TestRecordSamplest)},
538 {}};
539 InitTestRecordSample(data);
540
541 PerfRecordSample record;
542 record.Init((uint8_t *)&data, attr);
543 record.sampleType_ |= PERF_SAMPLE_CALLCHAIN;
544
545 record.callFrames_ = {};
546 std::vector<u64> ips = {0, 1, 2, 3};
547 record.data_.ips = ips.data();
548 record.data_.nr = ips.size();
549 record.ReplaceWithCallStack();
550 // not PERF_CONTEXT_USER will add
551 ASSERT_EQ(ips.size(), record.data_.nr);
552 for (size_t i = 0; i < record.data_.nr; i++) {
553 ASSERT_EQ(record.data_.ips[i], ips[i]);
554 }
555 // result is 0 - 3
556 }
557
558 const std::string RECORDNAME_READ = "read";
559 HWTEST_F(PerfEventRecordTest, Read, TestSize.Level1)
560 {
561 struct PerfRecordReadst {
562 perf_event_header h;
563 PerfRecordReadData d;
564 };
565 PerfRecordReadst data = {{PERF_RECORD_READ, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordReadst)},
566 {1, 2, {11, 12, 13, 14}}};
567
568 PerfRecordRead record;
569 record.Init((uint8_t *)&data);
570 ASSERT_EQ(record.GetType(), PERF_RECORD_READ);
571 ASSERT_EQ(record.GetName(), RECORDNAME_READ);
572 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
573 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
574 ASSERT_EQ(record.GetSize(), sizeof(data));
575
576 std::vector<uint8_t> buff;
577 ASSERT_TRUE(record.GetBinary(buff));
578 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
579 }
580
581 const std::string RECORDNAME_AUX = "aux";
582 HWTEST_F(PerfEventRecordTest, Aux, TestSize.Level1)
583 {
584 struct PerfRecordAuxst {
585 perf_event_header h;
586 PerfRecordAuxData d;
587 };
588 PerfRecordAuxst data = {{PERF_RECORD_AUX, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordAuxst)},
589 {1, 2, 3}};
590
591 PerfRecordAux record;
592 record.Init((uint8_t *)&data);
593 ASSERT_EQ(record.GetType(), PERF_RECORD_AUX);
594 ASSERT_EQ(record.GetName(), RECORDNAME_AUX);
595 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
596 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
597 ASSERT_EQ(record.GetSize(), sizeof(data));
598
599 std::vector<uint8_t> buff;
600 ASSERT_TRUE(record.GetBinary(buff));
601 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
602 }
603
604 const std::string RECORDNAME_ITRACE_START = "itraceStart";
605 HWTEST_F(PerfEventRecordTest, ItraceStart, TestSize.Level1)
606 {
607 struct PerfRecordItraceStartst {
608 perf_event_header h;
609 PerfRecordItraceStartData d;
610 };
611 PerfRecordItraceStartst data = {
612 {PERF_RECORD_ITRACE_START, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordItraceStartst)},
613 {1, 2}};
614
615 PerfRecordItraceStart record;
616 record.Init((uint8_t *)&data);
617 ASSERT_EQ(record.GetType(), PERF_RECORD_ITRACE_START);
618 ASSERT_EQ(record.GetName(), RECORDNAME_ITRACE_START);
619 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
620 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
621 ASSERT_EQ(record.GetSize(), sizeof(data));
622
623 std::vector<uint8_t> buff;
624 ASSERT_TRUE(record.GetBinary(buff));
625 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
626 }
627
628 const std::string RECORDNAME_LOST_SAMPLES = "lostSamples";
629 HWTEST_F(PerfEventRecordTest, LostSamples, TestSize.Level1)
630 {
631 struct PerfRecordLostSamplesst {
632 perf_event_header h;
633 PerfRecordLostSamplesData d;
634 };
635 PerfRecordLostSamplesst data = {
636 {PERF_RECORD_LOST_SAMPLES, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordLostSamplesst)},
637 {1}};
638
639 PerfRecordLostSamples record;
640 record.Init((uint8_t *)&data);
641 ASSERT_EQ(record.GetType(), PERF_RECORD_LOST_SAMPLES);
642 ASSERT_EQ(record.GetName(), RECORDNAME_LOST_SAMPLES);
643 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
644 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
645 ASSERT_EQ(record.GetSize(), sizeof(data));
646
647 std::vector<uint8_t> buff;
648 ASSERT_TRUE(record.GetBinary(buff));
649 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
650 }
651
652 const std::string RECORDNAME_SWITCH = "switch";
653 HWTEST_F(PerfEventRecordTest, Switch, TestSize.Level1)
654 {
655 struct PerfRecordSwitchst {
656 perf_event_header h;
657 PerfRecordSwitchData d;
658 };
659 PerfRecordSwitchst data = {
660 {PERF_RECORD_SWITCH, PERF_RECORD_MISC_KERNEL, sizeof(perf_event_header)},
661 {}};
662
663 PerfRecordSwitch record;
664 record.Init((uint8_t *)&data);
665 ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH);
666 ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH);
667 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
668 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
669 ASSERT_EQ(record.GetSize(), HEADER_SIZE);
670
671 std::vector<uint8_t> buff;
672 ASSERT_TRUE(record.GetBinary(buff));
673 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), HEADER_SIZE), 0);
674 }
675
676 const std::string RECORDNAME_SWITCH_CPU_WIDE = "switchCpuWide";
677 HWTEST_F(PerfEventRecordTest, SwitchCpuWide, TestSize.Level1)
678 {
679 struct PerfRecordSwitchCpuWidest {
680 perf_event_header h;
681 PerfRecordSwitchCpuWideData d;
682 };
683 PerfRecordSwitchCpuWidest data = {
684 {PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
685 {}};
686
687 PerfRecordSwitchCpuWide record;
688 record.Init((uint8_t *)&data);
689 ASSERT_EQ(record.GetType(), PERF_RECORD_SWITCH_CPU_WIDE);
690 ASSERT_EQ(record.GetName(), RECORDNAME_SWITCH_CPU_WIDE);
691 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
692 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
693 ASSERT_EQ(record.GetSize(), sizeof(data));
694
695 std::vector<uint8_t> buff;
696 ASSERT_TRUE(record.GetBinary(buff));
697 ASSERT_EQ(CompareByteStream((uint8_t *)&data, buff.data(), sizeof(data)), 0);
698 }
699
700 HWTEST_F(PerfEventRecordTest, GetPerfEventRecord, TestSize.Level1)
701 {
702 struct PerfRecordSwitchCpuWidest {
703 perf_event_header h;
704 PerfRecordSwitchCpuWideData d;
705 };
706 PerfRecordSwitchCpuWidest data = {
707 {PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
708 {}};
709 perf_event_attr attr {};
710 attr.sample_type = UINT64_MAX;
711 for (size_t type = PERF_RECORD_MMAP; type <= PERF_RECORD_MAX; type++) {
712 if (type == PERF_RECORD_SAMPLE) {
713 continue;
714 }
715 PerfEventRecord& perfEventRecord =
716 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(type),
717 reinterpret_cast<uint8_t *>(&data), attr);
718 if (type < PERF_RECORD_NAMESPACES) {
719 ASSERT_EQ(perfEventRecord.GetName() != nullptr, true);
720 }
721 }
722 PerfEventRecord& perfEventRecord =
723 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
724 reinterpret_cast<uint8_t *>(&data), attr);
725 ASSERT_EQ(perfEventRecord.GetName() != nullptr, true);
726 }
727
728 HWTEST_F(PerfEventRecordTest, GetPerfEventRecord2, TestSize.Level1)
729 {
730 struct PerfRecordSwitchCpuWidest {
731 perf_event_header h;
732 PerfRecordSwitchCpuWideData d;
733 };
734 PerfRecordSwitchCpuWidest data = {
735 {PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
736 {}};
737 perf_event_attr attr {};
738 attr.sample_type = UINT64_MAX;
739 PerfEventRecord& perfEventRecord1 =
740 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
741 reinterpret_cast<uint8_t *>(&data), attr);
742 PerfEventRecord& perfEventRecord2 =
743 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
744 reinterpret_cast<uint8_t *>(&data), attr);
745
746 ASSERT_TRUE(&perfEventRecord1 == &perfEventRecord2);
747 }
748
749 HWTEST_F(PerfEventRecordTest, GetPerfEventRecord3, TestSize.Level1)
750 {
751 struct PerfRecordSwitchCpuWidest {
752 perf_event_header h;
753 PerfRecordSwitchCpuWideData d;
754 };
755 PerfRecordSwitchCpuWidest data = {
756 {PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
757 {}};
758 perf_event_attr attr {};
759 attr.sample_type = UINT64_MAX;
760 PerfEventRecord& perfEventRecord1 =
761 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
762 reinterpret_cast<uint8_t *>(&data), attr);
763 PerfEventRecord& perfEventRecord2 =
764 PerfEventRecordFactory::GetPerfEventRecord(INT32_MAX,
765 reinterpret_cast<uint8_t *>(&data), attr);
766 ASSERT_TRUE(perfEventRecord1.GetName() != nullptr);
767 ASSERT_TRUE(perfEventRecord2.GetName() == nullptr);
768 }
769
770 HWTEST_F(PerfEventRecordTest, GetPerfEventRecord4, TestSize.Level1)
771 {
772 static constexpr size_t sizeOffset = 20;
773 std::vector<PerfRecordType> types = {
774 PERF_RECORD_MMAP,
775 PERF_RECORD_MMAP2,
776 PERF_RECORD_LOST,
777 PERF_RECORD_COMM,
778 PERF_RECORD_EXIT,
779 PERF_RECORD_THROTTLE,
780 PERF_RECORD_UNTHROTTLE,
781 PERF_RECORD_FORK,
782 PERF_RECORD_READ,
783 PERF_RECORD_AUX,
784 PERF_RECORD_AUXTRACE,
785 PERF_RECORD_ITRACE_START,
786 PERF_RECORD_LOST_SAMPLES,
787 PERF_RECORD_SWITCH,
788 PERF_RECORD_SWITCH_CPU_WIDE
789 };
790 perf_event_header header;
791 size_t size = sizeof(perf_event_header) + sizeOffset;
792 header.size = size;
793 uint8_t* data = static_cast<uint8_t*>(malloc(size));
794 ASSERT_EQ(memset_s(data, size, 0, size), 0);
795 ASSERT_EQ(memcpy_s(data, sizeof(perf_event_header),
796 reinterpret_cast<uint8_t*>(&header), sizeof(perf_event_header)), 0);
797 for (PerfRecordType type : types) {
798 perf_event_attr attr = {};
799 PerfEventRecord& record =
800 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(type),
801 data, attr);
802 EXPECT_NE(record.GetName(), nullptr);
803 }
804 free(data);
805 }
806
807 HWTEST_F(PerfEventRecordTest, GetPerfEventRecordMmap2, TestSize.Level1)
808 {
809 struct PerfRecordMmap2est {
810 perf_event_header h;
811 PerfRecordMmap2Data d;
812 };
813 constexpr uint32_t pid = 10;
814 constexpr uint32_t tid = 11;
815 constexpr uint32_t testNum1 = 12;
816 constexpr uint64_t addr = 111;
817 constexpr uint64_t testNum2 = 13;
818 PerfRecordMmap2est data = {
819 {PERF_RECORD_MMAP2, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordMmap2est)},
820 {pid, tid, addr, testNum2, testNum2, testNum1, testNum1, testNum2, testNum2,
821 testNum1, testNum1, "testdatammap2"}};
822 size_t size = HEADER_SIZE + sizeof(PerfRecordMmap2Data) - KILO + strlen(data.d.filename) + 1;
823 data.h.size = size;
824 perf_event_attr attr {};
825 attr.sample_type = UINT64_MAX;
826 PerfEventRecord& perfEventRecord1 =
827 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_MMAP2),
828 reinterpret_cast<uint8_t *>(&data), attr);
829 PerfRecordMmap2& record1 = static_cast<PerfRecordMmap2&>(perfEventRecord1);
830 EXPECT_EQ(record1.discard_, false);
831 record1.discard_ = true;
832 PerfEventRecord& perfEventRecord2 =
833 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_MMAP2),
834 reinterpret_cast<uint8_t *>(&data), attr);
835 PerfRecordMmap2& record2 = static_cast<PerfRecordMmap2&>(perfEventRecord2);
836 EXPECT_EQ(record2.discard_, false);
837 EXPECT_EQ(record2.GetType(), PERF_RECORD_MMAP2);
838 EXPECT_EQ(record2.GetName(), RECORDNAME_MMAP2);
839 EXPECT_EQ(record2.GetMisc(), PERF_RECORD_MISC_KERNEL);
840 EXPECT_EQ(record2.GetHeaderSize(), HEADER_SIZE);
841 EXPECT_EQ(record2.GetSize(), size);
842 EXPECT_EQ(record2.data_.pid, data.d.pid);
843 EXPECT_EQ(record2.data_.tid, data.d.tid);
844 EXPECT_EQ(record2.data_.addr, data.d.addr);
845 EXPECT_EQ(record2.data_.len, data.d.len);
846 EXPECT_EQ(record2.data_.pgoff, data.d.pgoff);
847 EXPECT_EQ(record2.data_.maj, data.d.maj);
848 EXPECT_EQ(record2.data_.min, data.d.min);
849 EXPECT_EQ(record2.data_.ino, data.d.ino);
850 EXPECT_EQ(record2.data_.prot, data.d.prot);
851 EXPECT_EQ(record2.data_.flags, data.d.flags);
852 EXPECT_EQ(strcmp(record2.data_.filename, data.d.filename), 0);
853 }
854
855 HWTEST_F(PerfEventRecordTest, MultiThreadGetPerfEventRecord, TestSize.Level1)
856 {
857 struct PerfRecordSwitchCpuWidest {
858 perf_event_header h;
859 PerfRecordSwitchCpuWideData d;
860 };
861 PerfRecordSwitchCpuWidest data = {
862 {PERF_RECORD_SWITCH_CPU_WIDE, PERF_RECORD_MISC_KERNEL, sizeof(PerfRecordSwitchCpuWidest)},
863 {}};
864 perf_event_attr attr {};
865 attr.sample_type = UINT64_MAX;
866 PerfEventRecord& perfEventRecord1 =
867 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
868 reinterpret_cast<uint8_t *>(&data), attr);
869
__anon5b235bed0102() 870 std::thread t1([&perfEventRecord1, &data, attr]() {
871 PerfEventRecord& perfEventRecord2 =
872 PerfEventRecordFactory::GetPerfEventRecord(static_cast<perf_event_type>(PERF_RECORD_AUXTRACE),
873 reinterpret_cast<uint8_t *>(&data), attr);
874 ASSERT_TRUE(&perfEventRecord1 != &perfEventRecord2);
875 });
876 t1.join();
877 }
878
879 HWTEST_F(PerfEventRecordTest, CreatePerfRecordMmap, TestSize.Level1)
880 {
881 perf_event_header header;
882 header.size = sizeof(PerfRecordMmapData) + sizeof(perf_event_header);
883 PerfRecordMmapData data;
884 for (uint32_t i = 0; i < KILO; i++) {
885 data.filename[i] = 'a';
886 }
887 size_t size = sizeof(PerfRecordMmapData) + sizeof(perf_event_header) + 10;
888 uint8_t* p = static_cast<uint8_t*>(malloc(size));
889 ASSERT_EQ(memset_s(p, size, 5, size), 0);
890 ASSERT_EQ(memcpy_s(p, sizeof(perf_event_header),
891 reinterpret_cast<uint8_t*>(&header), sizeof(perf_event_header)), 0);
892 ASSERT_EQ(memcpy_s(p + sizeof(perf_event_header), sizeof(PerfRecordMmapData),
893 reinterpret_cast<uint8_t*>(&data), sizeof(PerfRecordMmapData)), 0);
894
895 PerfRecordMmap record;
896 record.Init(p);
897 std::string str = record.data_.filename;
898 ASSERT_EQ(str.size(), KILO - 1);
899 for (char c : str) {
900 EXPECT_EQ(c, 'a');
901 }
902 free(p);
903 }
904
905 HWTEST_F(PerfEventRecordTest, CreatePerfRecordComm, TestSize.Level1)
906 {
907 perf_event_header header;
908 header.size = sizeof(PerfRecordCommData) + sizeof(perf_event_header);
909 PerfRecordCommData data;
910 for (uint32_t i = 0; i < KILO; i++) {
911 data.comm[i] = 'a';
912 }
913 size_t size = sizeof(PerfRecordCommData) + sizeof(perf_event_header) + 10;
914 uint8_t* p = static_cast<uint8_t*>(malloc(size));
915 ASSERT_EQ(memset_s(p, size, 5, size), 0);
916 ASSERT_EQ(memcpy_s(p, sizeof(perf_event_header),
917 reinterpret_cast<uint8_t*>(&header), sizeof(perf_event_header)), 0);
918 ASSERT_EQ(memcpy_s(p + sizeof(perf_event_header), sizeof(PerfRecordCommData),
919 reinterpret_cast<uint8_t*>(&data), sizeof(PerfRecordCommData)), 0);
920
921 PerfRecordComm record;
922 record.Init(p);
923 std::string str = record.data_.comm;
924 ASSERT_EQ(str.size(), KILO - 1);
925 for (char c : str) {
926 EXPECT_EQ(c, 'a');
927 }
928 free(p);
929 }
930
931 HWTEST_F(PerfEventRecordTest, CreatePerfRecordAuxtrace, TestSize.Level1)
932 {
933 perf_event_header header;
934 const char* rawData = "rawData";
935 size_t len = strlen(rawData) + 1;
936 header.size = sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header);
937 PerfRecordAuxtraceData data;
938 uint8_t* p = static_cast<uint8_t*>(malloc(header.size + len));
939 EXPECT_EQ(memset_s(p, header.size + len, 0, header.size + len), 0);
940 if (memcpy_s(p, sizeof(perf_event_header), reinterpret_cast<const uint8_t *>(&header),
941 sizeof(perf_event_header)) != 0) {
942 printf("memcpy_s perf_event_header return failed");
943 }
944 if (memcpy_s(p + sizeof(perf_event_header), sizeof(PerfRecordAuxtraceData),
945 reinterpret_cast<const uint8_t *>(&data), sizeof(PerfRecordAuxtraceData)) != 0) {
946 printf("memcpy_s data return failed");
947 }
948 if (memcpy_s(p + header.size, len, reinterpret_cast<const uint8_t *>(rawData), len) != 0) {
949 printf("memcpy_s rawData return failed");
950 }
951 PerfRecordAuxtrace record;
952 record.Init(p);
953 ASSERT_NE(record.rawData_, nullptr);
954 free(p);
955 }
956
957 HWTEST_F(PerfEventRecordTest, CreatePerfRecordAuxtrace2, TestSize.Level1)
958 {
959 PerfRecordAuxtrace* record = new PerfRecordAuxtrace();
960 record->Init(nullptr, {});
961
962 EXPECT_EQ(record->header_.type, PERF_RECORD_MMAP);
963 EXPECT_EQ(record->header_.misc, PERF_RECORD_MISC_USER);
964 EXPECT_EQ(record->header_.size, 0);
965
966 EXPECT_EQ(record->data_.size, 0);
967 EXPECT_EQ(record->data_.offset, 0);
968 EXPECT_EQ(record->data_.reference, 0);
969 EXPECT_EQ(record->data_.idx, 0);
970 EXPECT_EQ(record->data_.tid, 0);
971 EXPECT_EQ(record->data_.cpu, 0);
972 EXPECT_EQ(record->data_.reserved__, 0);
973
974 EXPECT_EQ(record->rawData_, nullptr);
975 }
976
977 HWTEST_F(PerfEventRecordTest, CreatePerfRecordAuxtrace3, TestSize.Level1)
978 {
979 PerfRecordAuxtrace* record = new PerfRecordAuxtrace();
980 record->Init(nullptr, {});
981 record->header_.type = PERF_RECORD_AUXTRACE;
982 record->header_.misc = PERF_RECORD_MISC_KERNEL;
983 record->header_.size = PERF_RECORD_AUXTRACE;
984 record->data_.size = 1;
985 record->data_.offset = 1;
986 record->data_.reference = 1;
987 record->data_.idx = 1;
988 record->data_.tid = 1;
989 record->data_.cpu = 1;
990 record->data_.reserved__ = 1;
991 std::shared_ptr<u8> ptr = std::make_shared<u8>();
992 record->rawData_ = ptr.get();
993
994 record->Init(nullptr, {});
995 EXPECT_EQ(record->header_.type, PERF_RECORD_MMAP);
996 EXPECT_EQ(record->header_.misc, PERF_RECORD_MISC_USER);
997 EXPECT_EQ(record->header_.size, 0);
998
999 EXPECT_EQ(record->data_.size, 0);
1000 EXPECT_EQ(record->data_.offset, 0);
1001 EXPECT_EQ(record->data_.reference, 0);
1002 EXPECT_EQ(record->data_.idx, 0);
1003 EXPECT_EQ(record->data_.tid, 0);
1004 EXPECT_EQ(record->data_.cpu, 0);
1005 EXPECT_EQ(record->data_.reserved__, 0);
1006
1007 EXPECT_EQ(record->rawData_, nullptr);
1008 }
1009
1010 HWTEST_F(PerfEventRecordTest, CreatePerfRecordSample, TestSize.Level1)
1011 {
1012 pid_t pid = fork();
1013 ASSERT_NE(pid, -1);
1014
1015 if (pid == 0) {
1016 PerfRecordSample record;
1017 perf_event_attr attr = {};
1018 attr.sample_type = PERF_SAMPLE_CALLCHAIN + PERF_SAMPLE_RAW + PERF_SAMPLE_BRANCH_STACK + PERF_SAMPLE_REGS_USER;
1019 std::vector<uint8_t> data = {};
1020 data.resize(200);
1021 for (auto i = 0; i < 200; i++) {
1022 data[i] = UINT8_MAX;
1023 }
1024 record.Init(data.data(), attr);
1025 _exit(-2);
1026 } else {
1027 int status = 0;
1028 waitpid(pid, &status, 0);
1029 ASSERT_TRUE(WIFEXITED(status));
1030 EXPECT_EQ(WEXITSTATUS(status), static_cast<uint8_t>(-1));
1031 }
1032 }
1033
1034 HWTEST_F(PerfEventRecordTest, SetDumpRemoveStack, TestSize.Level1)
1035 {
1036 bool dump = PerfRecordSample::IsDumpRemoveStack();
1037 PerfRecordSample::SetDumpRemoveStack(!dump);
1038 EXPECT_EQ(PerfRecordSample::IsDumpRemoveStack(), !dump);
1039 PerfRecordSample::SetDumpRemoveStack(dump);
1040 EXPECT_EQ(PerfRecordSample::IsDumpRemoveStack(), dump);
1041 }
1042
1043 HWTEST_F(PerfEventRecordTest, GetTime, TestSize.Level1)
1044 {
1045 static constexpr uint64_t time = 1234u;
1046 PerfRecordSample sample;
1047 sample.data_.time = time;
1048 EXPECT_EQ(sample.GetTime(), time);
1049 }
1050
1051 HWTEST_F(PerfEventRecordTest, AuxTraceInfo, TestSize.Level1)
1052 {
1053 constexpr uint32_t type = 4;
1054 constexpr uint32_t reserve = 0;
1055 constexpr uint64_t speType = 7;
1056 constexpr uint64_t cpuMmap = 2;
1057 struct PerfRecordAuxTraceInfost {
1058 perf_event_header h;
1059 PerfRecordAuxtraceInfoData d;
1060 };
1061 PerfRecordAuxTraceInfost data = {{PERF_RECORD_AUXTRACE_INFO, PERF_RECORD_MISC_KERNEL,
1062 static_cast<uint16_t>(sizeof(PerfRecordAuxTraceInfost))},
1063 {type, reserve, {speType, cpuMmap}}};
1064
1065 PerfRecordAuxTraceInfo record;
1066 record.Init((uint8_t *)&data);
1067 ASSERT_EQ(record.GetType(), PERF_RECORD_AUXTRACE_INFO);
1068 ASSERT_EQ(record.GetName(), PERF_RECORD_TYPE_AUXTRACEINFO);
1069 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
1070 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
1071 ASSERT_EQ(record.GetSize(), sizeof(data));
1072 ASSERT_EQ(record.data_.type, type);
1073 ASSERT_EQ(record.data_.priv[0], speType);
1074 ASSERT_EQ(record.data_.priv[1], cpuMmap);
1075 }
1076
1077 HWTEST_F(PerfEventRecordTest, TimeConv, TestSize.Level1)
1078 {
1079 constexpr uint64_t timeShift = 21;
1080 constexpr uint64_t timeDefalult = 1;
1081 constexpr uint8_t userTime = 1;
1082 struct PerfRecordTimeConvst {
1083 perf_event_header h;
1084 PerfRecordTtimeConvData d;
1085 };
1086 PerfRecordTimeConvst data = {{PERF_RECORD_TIME_CONV, PERF_RECORD_MISC_KERNEL,
1087 static_cast<uint16_t>(sizeof(PerfRecordTimeConvst))},
1088 {timeShift, timeDefalult, timeDefalult, timeDefalult, timeDefalult, userTime}};
1089
1090 PerfRecordTimeConv record;
1091 record.Init((uint8_t *)&data);
1092 ASSERT_EQ(record.GetType(), PERF_RECORD_TIME_CONV);
1093 ASSERT_EQ(record.GetName(), PERF_RECORD_TYPE_TIMECONV);
1094 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
1095 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
1096 ASSERT_EQ(record.GetSize(), sizeof(data));
1097 ASSERT_EQ(record.data_.time_shift, timeShift);
1098 ASSERT_EQ(record.data_.time_mult, timeDefalult);
1099 }
1100
1101 HWTEST_F(PerfEventRecordTest, CpuMap, TestSize.Level1)
1102 {
1103 constexpr uint16_t type = 0;
1104 constexpr uint16_t cpuNum = 16;
1105 struct PerfRecordCpuMapst {
1106 perf_event_header h;
1107 PerfRecordCpuMapData d;
1108 };
1109 PerfRecordCpuMapst data = {{PERF_RECORD_CPU_MAP, PERF_RECORD_MISC_KERNEL,
1110 static_cast<uint16_t>(sizeof(PerfRecordCpuMapst))},
1111 {type, cpuNum}};
1112
1113 PerfRecordCpuMap record;
1114 record.Init((uint8_t *)&data);
1115 ASSERT_EQ(record.GetType(), PERF_RECORD_CPU_MAP);
1116 ASSERT_EQ(record.GetName(), PERF_RECORD_TYPE_CPUMAP);
1117 ASSERT_EQ(record.GetMisc(), PERF_RECORD_MISC_KERNEL);
1118 ASSERT_EQ(record.GetHeaderSize(), HEADER_SIZE);
1119 ASSERT_EQ(record.GetSize(), sizeof(data));
1120 ASSERT_EQ(record.data_.nr, cpuNum);
1121 }
1122
1123 HWTEST_F(PerfEventRecordTest, AuxtraceInit, TestSize.Level1)
1124 {
1125 const char* rawData = "rawData";
1126 size_t len = strlen(rawData) + 1;
1127 perf_event_header header;
1128 header.size = sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header);
1129 header.type = PERF_RECORD_AUXTRACE;
1130 header.misc = PERF_RECORD_MISC_USER;
1131 PerfRecordAuxtraceData data;
1132 uint8_t* p = static_cast<uint8_t*>(malloc(header.size + len));
1133 EXPECT_EQ(memset_s(p, header.size + len, 0, header.size + len), 0);
1134 if (memcpy_s(p, sizeof(perf_event_header), reinterpret_cast<const uint8_t *>(&header),
1135 sizeof(perf_event_header)) != 0) {
1136 printf("memcpy_s perf_event_header return failed");
1137 }
1138 if (memcpy_s(p + sizeof(perf_event_header), sizeof(PerfRecordAuxtraceData),
1139 reinterpret_cast<const uint8_t *>(&data), sizeof(PerfRecordAuxtraceData)) != 0) {
1140 printf("memcpy_s data return failed");
1141 }
1142 if (memcpy_s(p + header.size, len, reinterpret_cast<const uint8_t *>(rawData), len) != 0) {
1143 printf("memcpy_s rawData return failed");
1144 }
1145 PerfRecordAuxtrace record;
1146 record.Init(p);
1147 ASSERT_NE(record.rawData_, nullptr);
1148 EXPECT_EQ(strcmp(reinterpret_cast<char*>(record.rawData_), "rawData"), 0);
1149 EXPECT_EQ(record.header_.type, PERF_RECORD_AUXTRACE);
1150 EXPECT_EQ(record.header_.misc, PERF_RECORD_MISC_USER);
1151 EXPECT_EQ(record.header_.size, sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header));
1152 EXPECT_EQ(record.data_.size, 0);
1153 EXPECT_EQ(record.data_.offset, 0);
1154 EXPECT_EQ(record.data_.reference, 0);
1155 EXPECT_EQ(record.data_.idx, 0);
1156 EXPECT_EQ(record.data_.tid, 0);
1157 EXPECT_EQ(record.data_.cpu, 0);
1158 EXPECT_EQ(record.data_.reserved__, 0);
1159 free(p);
1160 }
1161
1162 HWTEST_F(PerfEventRecordTest, GetBinary1, TestSize.Level1)
1163 {
1164 const char* rawData = "rawData";
1165 size_t len = strlen(rawData) + 1;
1166 perf_event_header header;
1167 header.size = sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header);
1168 header.type = PERF_RECORD_AUXTRACE;
1169 header.misc = PERF_RECORD_MISC_USER;
1170 PerfRecordAuxtraceData data;
1171 data.cpu = 1;
1172 data.idx = 1;
1173 data.offset = 2;
1174 data.reference = 2;
1175 data.reserved__ = 2;
1176 data.size = 1;
1177 data.tid = 1;
1178 uint8_t* p = static_cast<uint8_t*>(malloc(header.size + len));
1179 EXPECT_EQ(memset_s(p, header.size + len, 0, header.size + len), 0);
1180 EXPECT_EQ(memcpy_s(p, sizeof(perf_event_header), reinterpret_cast<const uint8_t *>(&header),
1181 sizeof(perf_event_header)), 0);
1182 EXPECT_EQ(memcpy_s(p + sizeof(perf_event_header), sizeof(PerfRecordAuxtraceData),
1183 reinterpret_cast<const uint8_t *>(&data), sizeof(PerfRecordAuxtraceData)), 0);
1184 EXPECT_EQ(memcpy_s(p + header.size, len, reinterpret_cast<const uint8_t *>(rawData), len), 0);
1185 PerfRecordAuxtrace record;
1186 PerfRecordAuxtrace recordCopy;
1187 record.Init(p);
1188 std::vector<u8> buf;
1189 ASSERT_TRUE(record.GetBinary1(buf));
1190 EXPECT_LT(buf.size(), record.GetSize());
1191 ASSERT_EQ(CompareByteStream(p, buf.data(), buf.size()), 0);
1192 recordCopy.Init(buf.data());
1193 EXPECT_EQ(recordCopy.header_.type, PERF_RECORD_AUXTRACE);
1194 EXPECT_EQ(recordCopy.header_.misc, PERF_RECORD_MISC_USER);
1195 EXPECT_EQ(recordCopy.header_.size, sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header));
1196 EXPECT_EQ(recordCopy.data_.size, 1);
1197 EXPECT_EQ(recordCopy.data_.offset, 2);
1198 EXPECT_EQ(recordCopy.data_.reference, 2);
1199 EXPECT_EQ(recordCopy.data_.idx, 1);
1200 EXPECT_EQ(recordCopy.data_.tid, 1);
1201 EXPECT_EQ(recordCopy.data_.cpu, 1);
1202 EXPECT_EQ(recordCopy.data_.reserved__, 2);
1203 free(p);
1204 }
1205
1206 HWTEST_F(PerfEventRecordTest, AuxtraceInitErr, TestSize.Level1)
1207 {
1208 perf_event_header header;
1209 header.size = sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header) - 1;
1210 header.type = PERF_RECORD_AUXTRACE;
1211 header.misc = PERF_RECORD_MISC_USER;
1212 PerfRecordAuxtraceData data;
1213 uint8_t* p = static_cast<uint8_t*>(malloc(header.size));
1214 EXPECT_EQ(memset_s(p, header.size, 0, header.size), 0);
1215 if (memcpy_s(p, sizeof(perf_event_header), reinterpret_cast<const uint8_t *>(&header),
1216 sizeof(perf_event_header)) != 0) {
1217 printf("memcpy_s perf_event_header return failed");
1218 }
1219 if (memcpy_s(p + sizeof(perf_event_header), sizeof(PerfRecordAuxtraceData),
1220 reinterpret_cast<const uint8_t *>(&data), sizeof(PerfRecordAuxtraceData)) != 0) {
1221 printf("memcpy_s data return failed");
1222 }
1223 PerfRecordAuxtrace record;
1224 record.Init(p);
1225 EXPECT_EQ(record.rawData_, nullptr);
1226 EXPECT_NE(record.header_.size, sizeof(PerfRecordAuxtraceData) + sizeof(perf_event_header));
1227 free(p);
1228 }
1229 } // namespace HiPerf
1230 } // namespace Developtools
1231 } // namespace OHOS
1232