1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <byteswap.h> 6 7 #include <algorithm> 8 #include <map> 9 #include <sstream> 10 #include <string> 11 #include <vector> 12 13 #include "base/logging.h" 14 15 #include "compat/string.h" 16 #include "compat/test.h" 17 #include "file_utils.h" 18 #include "perf_reader.h" 19 #include "perf_test_files.h" 20 #include "scoped_temp_path.h" 21 #include "test_perf_data.h" 22 #include "test_utils.h" 23 24 namespace quipper { 25 26 using PerfEvent = PerfDataProto_PerfEvent; 27 using SampleEvent = PerfDataProto_SampleEvent; 28 using SampleInfo = PerfDataProto_SampleInfo; 29 30 TEST(PerfReaderTest, PipedData_IncompleteEventHeader) { 31 std::stringstream input; 32 33 // pipe header 34 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 35 36 // data 37 38 // PERF_RECORD_HEADER_ATTR 39 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP, 40 true /*sample_id_all*/) 41 .WithConfig(123) 42 .WriteTo(&input); 43 44 // PERF_RECORD_HEADER_EVENT_TYPE 45 const struct event_type_event event_type = { 46 .header = 47 { 48 .type = PERF_RECORD_HEADER_EVENT_TYPE, 49 .misc = 0, 50 .size = sizeof(struct event_type_event), 51 }, 52 .event_type = { 53 /*event_id*/ 123, 54 /*name*/ "cycles", 55 }, 56 }; 57 input.write(reinterpret_cast<const char*>(&event_type), sizeof(event_type)); 58 59 // Incomplete data at the end: 60 input << string(sizeof(struct perf_event_header) - 1, '\0'); 61 62 // 63 // Parse input. 64 // 65 66 PerfReader pr; 67 ASSERT_TRUE(pr.ReadFromString(input.str())); 68 69 // Make sure the attr was recorded properly. 70 ASSERT_EQ(1, pr.attrs().size()); 71 EXPECT_EQ(123, pr.attrs().Get(0).attr().config()); 72 ASSERT_EQ(1, pr.event_types().size()); 73 EXPECT_EQ("cycles", pr.event_types().Get(0).name()); 74 75 // Make sure metadata mask was set to indicate EVENT_TYPE was upgraded 76 // to EVENT_DESC. 77 EXPECT_EQ((1 << HEADER_EVENT_DESC), pr.metadata_mask()); 78 } 79 80 TEST(PerfReaderTest, PipedData_IncompleteEventData) { 81 std::stringstream input; 82 83 // pipe header 84 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 85 86 // data 87 88 // PERF_RECORD_HEADER_ATTR 89 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP, 90 true /*sample_id_all*/) 91 .WithConfig(456) 92 .WriteTo(&input); 93 94 // PERF_RECORD_HEADER_EVENT_TYPE 95 const struct event_type_event event_type = { 96 .header = 97 { 98 .type = PERF_RECORD_HEADER_EVENT_TYPE, 99 .misc = 0, 100 .size = sizeof(struct event_type_event), 101 }, 102 .event_type = { 103 /*event_id*/ 456, 104 /*name*/ "instructions", 105 }, 106 }; 107 input.write(reinterpret_cast<const char*>(&event_type), sizeof(event_type)); 108 109 // Incomplete data at the end: 110 // Header: 111 const struct perf_event_header incomplete_event_header = { 112 .type = PERF_RECORD_SAMPLE, 113 .misc = 0, 114 .size = sizeof(perf_event_header) + 10, 115 }; 116 input.write(reinterpret_cast<const char*>(&incomplete_event_header), 117 sizeof(incomplete_event_header)); 118 // Incomplete event: 119 input << string(3, '\0'); 120 121 // 122 // Parse input. 123 // 124 125 PerfReader pr; 126 ASSERT_TRUE(pr.ReadFromString(input.str())); 127 128 // Make sure the attr was recorded properly. 129 ASSERT_EQ(1, pr.attrs().size()); 130 EXPECT_EQ(456, pr.attrs().Get(0).attr().config()); 131 ASSERT_EQ(1, pr.event_types().size()); 132 EXPECT_EQ("instructions", pr.event_types().Get(0).name()); 133 134 // Make sure metadata mask was set to indicate EVENT_TYPE was upgraded 135 // to EVENT_DESC. 136 EXPECT_EQ((1 << HEADER_EVENT_DESC), pr.metadata_mask()); 137 } 138 139 TEST(PerfReaderTest, CorruptedFiles) { 140 for (const char* test_file : 141 perf_test_files::GetCorruptedPerfPipedDataFiles()) { 142 string input_perf_data = GetTestInputFilePath(test_file); 143 LOG(INFO) << "Testing " << input_perf_data; 144 ASSERT_TRUE(FileExists(input_perf_data)) << "Test file does not exist!"; 145 PerfReader pr; 146 ASSERT_FALSE(pr.ReadFile(input_perf_data)); 147 } 148 } 149 150 TEST(PerfReaderTest, ReadsAndWritesPipedModeAuxEvents) { 151 std::stringstream input; 152 153 // header 154 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 155 156 // data 157 158 // PERF_RECORD_HEADER_ATTR 159 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP, 160 false /*sample_id_all*/) 161 .WriteTo(&input); 162 163 // PERF_RECORD_AUX 164 struct aux_event written_aux_event = { 165 .header = 166 { 167 .type = PERF_RECORD_AUX, 168 .misc = 0, 169 .size = sizeof(struct aux_event), 170 }, 171 .aux_offset = 0x2000, 172 .aux_size = 16, 173 .flags = PERF_AUX_FLAG_TRUNCATED | PERF_AUX_FLAG_PARTIAL, 174 }; 175 input.write(reinterpret_cast<const char*>(&written_aux_event), 176 sizeof(struct aux_event)); 177 178 // 179 // Parse input. 180 // 181 182 PerfReader pr1; 183 ASSERT_TRUE(pr1.ReadFromString(input.str())); 184 // Write it out and read it in again, the two should have the same data. 185 std::vector<char> output_perf_data; 186 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 187 PerfReader pr2; 188 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 189 190 // Test both versions: 191 for (PerfReader* pr : {&pr1, &pr2}) { 192 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 193 EXPECT_EQ(1, pr->events().size()); 194 195 const PerfEvent& event = pr->events().Get(0); 196 EXPECT_EQ(PERF_RECORD_AUX, event.header().type()); 197 EXPECT_EQ(0x2000, event.aux_event().aux_offset()); 198 EXPECT_EQ(16, event.aux_event().aux_size()); 199 EXPECT_TRUE(event.aux_event().is_truncated()); 200 EXPECT_FALSE(event.aux_event().is_overwrite()); 201 EXPECT_TRUE(event.aux_event().is_partial()); 202 } 203 } 204 205 TEST(PerfReaderTest, ReadsAndWritesPipedModeAuxTraceEvents) { 206 std::stringstream input; 207 208 // header 209 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 210 211 // data 212 213 // PERF_RECORD_HEADER_ATTR 214 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP, 215 false /*sample_id_all*/) 216 .WriteTo(&input); 217 218 // PERF_RECORD_AUXTRACE 219 testing::ExampleAuxtraceEvent(9, 0x2000, 7, 3, 0x68d, 4, 0, "/dev/zero") 220 .WriteTo(&input); 221 222 // 223 // Parse input. 224 // 225 226 PerfReader pr1; 227 ASSERT_TRUE(pr1.ReadFromString(input.str())); 228 // Write it out and read it in again, the two should have the same data. 229 std::vector<char> output_perf_data; 230 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 231 PerfReader pr2; 232 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 233 234 // Test both versions: 235 for (PerfReader* pr : {&pr1, &pr2}) { 236 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 237 EXPECT_EQ(1, pr->events().size()); 238 239 const PerfEvent& event = pr->events().Get(0); 240 EXPECT_EQ(PERF_RECORD_AUXTRACE, event.header().type()); 241 EXPECT_EQ(9, event.auxtrace_event().size()); 242 EXPECT_EQ(0x2000, event.auxtrace_event().offset()); 243 EXPECT_EQ(7, event.auxtrace_event().reference()); 244 EXPECT_EQ(3, event.auxtrace_event().idx()); 245 EXPECT_EQ(0x68d, event.auxtrace_event().tid()); 246 EXPECT_EQ(4, event.auxtrace_event().cpu()); 247 EXPECT_EQ("/dev/zero", event.auxtrace_event().trace_data()); 248 } 249 } 250 251 TEST(PerfReaderTest, ReadsAndWritesAuxTraceEvents) { 252 std::stringstream input; 253 254 // PERF_RECORD_AUXTRACE 255 testing::ExampleAuxtraceEvent auxtrace_event(9, 0x2000, 7, 3, 0x68d, 4, 0, 256 "/dev/zero"); 257 const size_t data_size = 258 auxtrace_event.GetSize() + auxtrace_event.GetTraceSize(); 259 260 // header 261 testing::ExamplePerfDataFileHeader file_header((0)); 262 file_header.WithAttrCount(1).WithDataSize(data_size); 263 file_header.WriteTo(&input); 264 265 // attrs 266 ASSERT_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 267 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP, false /*sample_id_all*/) 268 .WriteTo(&input); 269 270 // data 271 ASSERT_EQ(file_header.header().data.offset, static_cast<u64>(input.tellp())); 272 auxtrace_event.WriteTo(&input); 273 274 // 275 // Parse input. 276 // 277 278 PerfReader pr1; 279 ASSERT_TRUE(pr1.ReadFromString(input.str())); 280 // Write it out and read it in again, the two should have the same data. 281 std::vector<char> output_perf_data; 282 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 283 PerfReader pr2; 284 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 285 286 // Test both versions: 287 for (PerfReader* pr : {&pr1, &pr2}) { 288 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 289 EXPECT_EQ(1, pr->events().size()); 290 291 const PerfEvent& event = pr->events().Get(0); 292 EXPECT_EQ(PERF_RECORD_AUXTRACE, event.header().type()); 293 EXPECT_EQ(9, event.auxtrace_event().size()); 294 EXPECT_EQ(0x2000, event.auxtrace_event().offset()); 295 EXPECT_EQ(7, event.auxtrace_event().reference()); 296 EXPECT_EQ(3, event.auxtrace_event().idx()); 297 EXPECT_EQ(0x68d, event.auxtrace_event().tid()); 298 EXPECT_EQ(4, event.auxtrace_event().cpu()); 299 EXPECT_EQ("/dev/zero", event.auxtrace_event().trace_data()); 300 } 301 } 302 303 TEST(PerfReaderTest, ReadsAndWritesTraceMetadata) { 304 std::stringstream input; 305 306 const size_t data_size = 307 testing::ExamplePerfSampleEvent_Tracepoint::kEventSize; 308 309 // header 310 testing::ExamplePerfDataFileHeader file_header(1 << HEADER_TRACING_DATA); 311 file_header.WithAttrCount(1).WithDataSize(data_size); 312 file_header.WriteTo(&input); 313 const perf_file_header& header = file_header.header(); 314 315 // attrs 316 CHECK_EQ(header.attrs.offset, static_cast<u64>(input.tellp())); 317 testing::ExamplePerfFileAttr_Tracepoint(73).WriteTo(&input); 318 319 // data 320 ASSERT_EQ(header.data.offset, static_cast<u64>(input.tellp())); 321 testing::ExamplePerfSampleEvent_Tracepoint().WriteTo(&input); 322 ASSERT_EQ(file_header.data_end(), input.tellp()); 323 324 // metadata 325 326 const unsigned int metadata_count = 1; 327 328 // HEADER_TRACING_DATA 329 testing::ExampleTracingMetadata tracing_metadata( 330 file_header.data_end() + metadata_count * sizeof(perf_file_section)); 331 332 // write metadata index entries 333 tracing_metadata.index_entry().WriteTo(&input); 334 // write metadata 335 tracing_metadata.data().WriteTo(&input); 336 337 // 338 // Parse input. 339 // 340 341 PerfReader pr; 342 ASSERT_TRUE(pr.ReadFromString(input.str())); 343 344 EXPECT_EQ(tracing_metadata.data().value(), pr.tracing_data()); 345 346 // Write it out and read it in again, it should still be good: 347 std::vector<char> output_perf_data; 348 EXPECT_TRUE(pr.WriteToVector(&output_perf_data)); 349 EXPECT_TRUE(pr.ReadFromVector(output_perf_data)); 350 EXPECT_EQ(tracing_metadata.data().value(), pr.tracing_data()); 351 } 352 353 TEST(PerfReaderTest, ReadsTracingMetadataEvent) { 354 std::stringstream input; 355 356 // pipe header 357 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 358 359 // data 360 361 const char raw_data[] = "\x17\x08\x44tracing0.5BLAHBLAHBLAH...."; 362 const string trace_metadata(raw_data, sizeof(raw_data) - 1); 363 364 const tracing_data_event trace_event = { 365 .header = 366 { 367 .type = PERF_RECORD_HEADER_TRACING_DATA, 368 .misc = 0, 369 .size = sizeof(tracing_data_event), 370 }, 371 .size = static_cast<u32>(trace_metadata.size()), 372 }; 373 374 input.write(reinterpret_cast<const char*>(&trace_event), sizeof(trace_event)); 375 input.write(trace_metadata.data(), trace_metadata.size()); 376 377 // 378 // Parse input. 379 // 380 381 PerfReader pr; 382 ASSERT_TRUE(pr.ReadFromString(input.str())); 383 EXPECT_EQ(trace_metadata, pr.tracing_data()); 384 385 // Write it out and read it in again, tracing_data() should still be correct. 386 // NB: It does not get written as an event, but in a metadata section. 387 std::vector<char> output_perf_data; 388 EXPECT_TRUE(pr.WriteToVector(&output_perf_data)); 389 EXPECT_TRUE(pr.ReadFromVector(output_perf_data)); 390 EXPECT_EQ(trace_metadata, pr.tracing_data()); 391 } 392 393 // Regression test for http://crbug.com/484393 394 TEST(PerfReaderTest, BranchStackMetadataIndexHasZeroSize) { 395 std::stringstream input; 396 397 const size_t data_size = 398 testing::ExamplePerfSampleEvent_BranchStack::kEventSize; 399 400 // header 401 testing::ExamplePerfDataFileHeader file_header(1 << HEADER_BRANCH_STACK); 402 file_header.WithAttrCount(1).WithDataSize(data_size); 403 file_header.WriteTo(&input); 404 const perf_file_header& header = file_header.header(); 405 406 // attrs 407 CHECK_EQ(header.attrs.offset, static_cast<u64>(input.tellp())); 408 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_BRANCH_STACK, 409 false /*sample_id_all*/) 410 .WriteTo(&input); 411 412 // data 413 ASSERT_EQ(header.data.offset, static_cast<u64>(input.tellp())); 414 testing::ExamplePerfSampleEvent_BranchStack().WriteTo(&input); 415 ASSERT_EQ(file_header.data_end(), input.tellp()); 416 417 // metadata 418 419 // HEADER_BRANCH_STACK 420 const perf_file_section branch_stack_index = { 421 .offset = file_header.data_end_offset(), 422 .size = 0, 423 }; 424 input.write(reinterpret_cast<const char*>(&branch_stack_index), 425 sizeof(branch_stack_index)); 426 427 // 428 // Parse input. 429 // 430 431 PerfReader pr; 432 ASSERT_TRUE(pr.ReadFromString(input.str())); 433 434 // Write it out again. 435 // Initialize the buffer to a non-zero sentinel value so that the bytes 436 // we are checking were written with zero must have been written. 437 const size_t max_predicted_written_size = 1024; 438 std::vector<char> output_perf_data(max_predicted_written_size, '\xaa'); 439 EXPECT_TRUE(pr.WriteToVector(&output_perf_data)); 440 EXPECT_LE(output_perf_data.size(), max_predicted_written_size) 441 << "Bad prediction for written size"; 442 443 // Specifically check that the metadata index has zero in the size. 444 const auto* output_header = 445 reinterpret_cast<struct perf_file_header*>(output_perf_data.data()); 446 EXPECT_EQ(1 << HEADER_BRANCH_STACK, output_header->adds_features[0]) 447 << "Expected just a HEADER_BRANCH_STACK feature"; 448 const size_t metadata_offset = 449 output_header->data.offset + output_header->data.size; 450 const auto* output_feature_index = 451 reinterpret_cast<struct perf_file_section*>(output_perf_data.data() + 452 metadata_offset); 453 EXPECT_EQ(0, output_feature_index[0].size) 454 << "Regression: Expected zero size for the HEADER_BRANCH_STACK feature " 455 << "metadata index"; 456 } 457 458 // Regression test for http://crbug.com/427767 459 TEST(PerfReaderTest, CorrectlyReadsPerfEventAttrSize) { 460 std::stringstream input; 461 462 // pipe header 463 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 464 465 // data 466 467 struct old_perf_event_attr { 468 __u32 type; 469 __u32 size; 470 __u64 config; 471 // clang-format off 472 // union { 473 __u64 sample_period; 474 // __u64 sample_freq; 475 // }; 476 // clang-format on 477 __u64 sample_type; 478 __u64 read_format; 479 // Skip the rest of the fields from perf_event_attr to simulate an 480 // older, smaller version of the struct. 481 }; 482 483 struct old_attr_event { 484 struct perf_event_header header; 485 struct old_perf_event_attr attr; 486 u64 id[]; 487 }; 488 489 const old_attr_event attr = { 490 .header = 491 { 492 .type = PERF_RECORD_HEADER_ATTR, 493 .misc = 0, 494 // A count of 8 ids is carefully selected to make the event exceed 495 // 96 bytes (sizeof(perf_event_attr)) so that the test fails 496 // instead of crashes with the old code. 497 .size = sizeof(old_attr_event) + 8 * sizeof(u64), 498 }, 499 .attr = 500 { 501 .type = 0, 502 .size = sizeof(old_perf_event_attr), 503 .config = 0, 504 .sample_period = 10000001, 505 .sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | 506 PERF_SAMPLE_TIME | PERF_SAMPLE_ID | 507 PERF_SAMPLE_CPU, 508 .read_format = PERF_FORMAT_ID, 509 }, 510 }; 511 512 input.write(reinterpret_cast<const char*>(&attr), sizeof(attr)); 513 for (u64 id : {301, 302, 303, 304, 305, 306, 307, 308}) 514 input.write(reinterpret_cast<const char*>(&id), sizeof(id)); 515 516 // Add some sample events so that there's something to over-read. 517 const sample_event sample = { 518 .header = { 519 .type = PERF_RECORD_SAMPLE, 520 .misc = 0, 521 .size = sizeof(perf_event_header) + 5 * sizeof(u64), 522 }}; 523 // We don't care about the contents of the SAMPLE events, except for the ID, 524 // which is needed to determine the attr for reading sample info. 525 const u64 sample_event_array[] = { 526 0, // IP 527 0, // TID 528 0, // TIME 529 308, // ID 530 0, // CPU 531 }; 532 533 for (int i = 0; i < 20; i++) { 534 input.write(reinterpret_cast<const char*>(&sample), sizeof(sample)); 535 input.write(reinterpret_cast<const char*>(sample_event_array), 536 sizeof(sample_event_array)); 537 } 538 539 // 540 // Parse input. 541 // 542 543 PerfReader pr; 544 ASSERT_TRUE(pr.ReadFromString(input.str())); 545 ASSERT_EQ(pr.attrs().size(), 1); 546 const auto& actual_attr = pr.attrs().Get(0); 547 ASSERT_EQ(8, actual_attr.ids().size()); 548 EXPECT_EQ(301, actual_attr.ids(0)); 549 EXPECT_EQ(302, actual_attr.ids(1)); 550 EXPECT_EQ(303, actual_attr.ids(2)); 551 EXPECT_EQ(304, actual_attr.ids(3)); 552 } 553 554 // Tests all sample info fields. When support for new sample_info fields are 555 // added to quipper, update this test accordingly. 556 TEST(PerfReaderTest, ReadsAndWritesSampleEvent) { 557 using testing::PunU32U64; 558 559 std::stringstream input; 560 561 // header 562 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 563 564 // data 565 566 // PERF_RECORD_HEADER_ATTR 567 const u64 sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | 568 PERF_SAMPLE_ADDR | PERF_SAMPLE_READ | 569 PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_CPU | 570 PERF_SAMPLE_ID | PERF_SAMPLE_PERIOD | 571 PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_BRANCH_STACK; 572 573 const size_t num_sample_event_bits = 10; 574 // not tested: 575 // PERF_SAMPLE_RAW | 576 testing::ExamplePerfEventAttrEvent_Hardware(sample_type, 577 true /*sample_id_all*/) 578 .WithId(401) 579 .WithReadFormat(PERF_FORMAT_TOTAL_TIME_ENABLED | 580 PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID) 581 .WriteTo(&input); 582 583 // PERF_RECORD_SAMPLE 584 const size_t call_chain_size = 6; 585 const size_t branch_stack_size = 5; 586 const sample_event written_sample_event = { 587 .header = { 588 .type = PERF_RECORD_SAMPLE, 589 .misc = PERF_RECORD_MISC_KERNEL, 590 .size = 591 sizeof(struct sample_event) + 592 num_sample_event_bits * sizeof(u64) + 593 4 * sizeof( 594 u64) + // Non-grouped read info, see 595 // perf_event_read_format in kernel/perf_event.h. 596 call_chain_size * sizeof(u64) + 597 branch_stack_size * sizeof(struct branch_entry), 598 }}; 599 const u64 sample_event_array[] = { 600 0xffffffff01234567, // IP 601 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid) 602 1415837014 * 1000000000ULL, // TIME 603 0x00007f999c38d15a, // ADDR 604 401, // ID 605 1, // STREAM_ID 606 8, // CPU 607 10001, // PERIOD 608 609 // READ 610 0x103c5d0, // value 611 0x7f6e8c45a920, // time_enabled 612 0x7ffed1a5e950, // time_running 613 402, // id 614 615 // clang-format off 616 // CALLCHAIN 617 6, // nr 618 0x1c1000, // ips 619 0x1c2000, 620 0x1c3000, 621 0x2c0000, 622 0x2c1000, 623 0x3c1000, 624 625 // BRANCH_STACK 626 5, // nr 627 0x00007f4a313bb8cc, 0x00007f4a313bdb40, 0x02, // entries 628 0x00007f4a30ce4de2, 0x00007f4a313bb8b3, 0x02, // predicted = 0x2 629 0x00007f4a313bb8b0, 0x00007f4a30ce4de0, 0x01, // mispredict = 0x1 630 0x00007f4a30ff45c1, 0x00007f4a313bb8a0, 0x02, 631 0x00007f4a30ff49f2, 0x00007f4a30ff45bb, 0x02, 632 // clang-format on 633 }; 634 ASSERT_EQ(written_sample_event.header.size, 635 sizeof(written_sample_event.header) + sizeof(sample_event_array)); 636 input.write(reinterpret_cast<const char*>(&written_sample_event), 637 sizeof(written_sample_event)); 638 input.write(reinterpret_cast<const char*>(sample_event_array), 639 sizeof(sample_event_array)); 640 641 // 642 // Parse input. 643 // 644 645 PerfReader pr1; 646 ASSERT_TRUE(pr1.ReadFromString(input.str())); 647 // Write it out and read it in again, the two should have the same data. 648 std::vector<char> output_perf_data; 649 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 650 PerfReader pr2; 651 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 652 653 // Test both versions: 654 for (PerfReader* pr : {&pr1, &pr2}) { 655 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 656 EXPECT_EQ(1, pr->events().size()); 657 658 const PerfEvent& event = pr->events().Get(0); 659 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 660 661 const SampleEvent& sample = event.sample_event(); 662 EXPECT_EQ(0xffffffff01234567, sample.ip()); 663 EXPECT_EQ(0x68d, sample.pid()); 664 EXPECT_EQ(0x68e, sample.tid()); 665 EXPECT_EQ(1415837014 * 1000000000ULL, sample.sample_time_ns()); 666 EXPECT_EQ(0x00007f999c38d15a, sample.addr()); 667 EXPECT_EQ(401, sample.id()); 668 EXPECT_EQ(1, sample.stream_id()); 669 EXPECT_EQ(8, sample.cpu()); 670 EXPECT_EQ(10001, sample.period()); 671 672 // Read info 673 EXPECT_TRUE(sample.has_read_info()); 674 EXPECT_EQ(0x7f6e8c45a920, sample.read_info().time_enabled()); 675 EXPECT_EQ(0x7ffed1a5e950, sample.read_info().time_running()); 676 ASSERT_EQ(1, sample.read_info().read_value_size()); 677 EXPECT_EQ(0x103c5d0, sample.read_info().read_value(0).value()); 678 EXPECT_EQ(402, sample.read_info().read_value(0).id()); 679 680 // Callchain. 681 ASSERT_EQ(6, sample.callchain_size()); 682 EXPECT_EQ(0x1c1000, sample.callchain(0)); 683 EXPECT_EQ(0x1c2000, sample.callchain(1)); 684 EXPECT_EQ(0x1c3000, sample.callchain(2)); 685 EXPECT_EQ(0x2c0000, sample.callchain(3)); 686 EXPECT_EQ(0x2c1000, sample.callchain(4)); 687 EXPECT_EQ(0x3c1000, sample.callchain(5)); 688 689 // Branch stack. 690 ASSERT_EQ(5, sample.branch_stack_size()); 691 EXPECT_EQ(0x00007f4a313bb8cc, sample.branch_stack(0).from_ip()); 692 EXPECT_EQ(0x00007f4a313bdb40, sample.branch_stack(0).to_ip()); 693 EXPECT_FALSE(sample.branch_stack(0).mispredicted()); 694 EXPECT_EQ(0x00007f4a30ce4de2, sample.branch_stack(1).from_ip()); 695 EXPECT_EQ(0x00007f4a313bb8b3, sample.branch_stack(1).to_ip()); 696 EXPECT_FALSE(sample.branch_stack(1).mispredicted()); 697 EXPECT_EQ(0x00007f4a313bb8b0, sample.branch_stack(2).from_ip()); 698 EXPECT_EQ(0x00007f4a30ce4de0, sample.branch_stack(2).to_ip()); 699 EXPECT_TRUE(sample.branch_stack(2).mispredicted()); 700 EXPECT_EQ(0x00007f4a30ff45c1, sample.branch_stack(3).from_ip()); 701 EXPECT_EQ(0x00007f4a313bb8a0, sample.branch_stack(3).to_ip()); 702 EXPECT_FALSE(sample.branch_stack(3).mispredicted()); 703 EXPECT_EQ(0x00007f4a30ff49f2, sample.branch_stack(4).from_ip()); 704 EXPECT_EQ(0x00007f4a30ff45bb, sample.branch_stack(4).to_ip()); 705 EXPECT_FALSE(sample.branch_stack(4).mispredicted()); 706 } 707 } 708 709 TEST(PerfReaderTest, ReadsAndWritesSampleEventMissingTime) { 710 using testing::PunU32U64; 711 712 std::stringstream input; 713 714 // header 715 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 716 717 // data 718 719 // PERF_RECORD_HEADER_ATTR 720 const u64 sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ | PERF_SAMPLE_ID; 721 const size_t num_sample_event_bits = 2; 722 testing::ExamplePerfEventAttrEvent_Hardware(sample_type, 723 true /*sample_id_all*/) 724 .WithId(401) 725 .WithReadFormat(PERF_FORMAT_ID) 726 .WriteTo(&input); 727 const sample_event written_sample_event = { 728 .header = { 729 .type = PERF_RECORD_SAMPLE, 730 .misc = 0, 731 .size = sizeof(struct sample_event) + 732 num_sample_event_bits * sizeof(u64) + 733 2 * sizeof(u64), // Non-grouped read info (without times!). 734 }}; 735 const u64 sample_event_array[] = { 736 0xffffffff01234567, // IP 737 401, // ID 738 // READ 739 0x103c5d0, // value 740 402, // id 741 }; 742 ASSERT_EQ(written_sample_event.header.size, 743 sizeof(written_sample_event.header) + sizeof(sample_event_array)); 744 input.write(reinterpret_cast<const char*>(&written_sample_event), 745 sizeof(written_sample_event)); 746 input.write(reinterpret_cast<const char*>(sample_event_array), 747 sizeof(sample_event_array)); 748 749 // 750 // Parse input. 751 // 752 753 PerfReader pr1; 754 ASSERT_TRUE(pr1.ReadFromString(input.str())); 755 // Write it out and read it in again, the two should have the same data. 756 std::vector<char> output_perf_data; 757 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 758 PerfReader pr2; 759 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 760 761 // Test both versions: 762 for (PerfReader* pr : {&pr1, &pr2}) { 763 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 764 EXPECT_EQ(1, pr->events().size()); 765 766 const PerfEvent& event = pr->events().Get(0); 767 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 768 769 const SampleEvent& sample = event.sample_event(); 770 EXPECT_EQ(0xffffffff01234567, sample.ip()); 771 EXPECT_EQ(401, sample.id()); 772 773 // Read info 774 EXPECT_TRUE(sample.has_read_info()); 775 EXPECT_FALSE(sample.read_info().has_time_enabled()); 776 EXPECT_FALSE(sample.read_info().has_time_running()); 777 ASSERT_EQ(1, sample.read_info().read_value_size()); 778 EXPECT_EQ(0x103c5d0, sample.read_info().read_value(0).value()); 779 EXPECT_EQ(402, sample.read_info().read_value(0).id()); 780 } 781 } 782 783 TEST(PerfReaderTest, ReadsAndWritesSampleAndSampleIdAll) { 784 using testing::PunU32U64; 785 786 std::stringstream input; 787 788 // header 789 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 790 791 // data 792 793 // PERF_RECORD_HEADER_ATTR 794 // clang-format off 795 const u64 sample_type = // * == in sample_id_all 796 PERF_SAMPLE_IP | 797 PERF_SAMPLE_TID | // * 798 PERF_SAMPLE_TIME | // * 799 PERF_SAMPLE_ADDR | 800 PERF_SAMPLE_ID | // * 801 PERF_SAMPLE_STREAM_ID | // * 802 PERF_SAMPLE_CPU | // * 803 PERF_SAMPLE_PERIOD; 804 // clang-format on 805 const size_t num_sample_event_bits = 8; 806 const size_t num_sample_id_bits = 5; 807 // not tested: 808 // PERF_SAMPLE_READ | 809 // PERF_SAMPLE_RAW | 810 // PERF_SAMPLE_CALLCHAIN | 811 // PERF_SAMPLE_BRANCH_STACK | 812 testing::ExamplePerfEventAttrEvent_Hardware(sample_type, 813 true /*sample_id_all*/) 814 .WithId(401) 815 .WriteTo(&input); 816 817 // PERF_RECORD_SAMPLE 818 const sample_event written_sample_event = { 819 .header = { 820 .type = PERF_RECORD_SAMPLE, 821 .misc = PERF_RECORD_MISC_KERNEL, 822 .size = 823 sizeof(struct sample_event) + num_sample_event_bits * sizeof(u64), 824 }}; 825 const u64 sample_event_array[] = { 826 0xffffffff01234567, // IP 827 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid) 828 1415837014 * 1000000000ULL, // TIME 829 0x00007f999c38d15a, // ADDR 830 401, // ID 831 1, // STREAM_ID 832 8, // CPU 833 10001, // PERIOD 834 }; 835 ASSERT_EQ(written_sample_event.header.size, 836 sizeof(written_sample_event.header) + sizeof(sample_event_array)); 837 input.write(reinterpret_cast<const char*>(&written_sample_event), 838 sizeof(written_sample_event)); 839 input.write(reinterpret_cast<const char*>(sample_event_array), 840 sizeof(sample_event_array)); 841 842 // PERF_RECORD_MMAP 843 ASSERT_EQ(40, offsetof(struct mmap_event, filename)); 844 // clang-format off 845 const size_t mmap_event_size = 846 offsetof(struct mmap_event, filename) + 10 + 847 6 /* ==16, nearest 64-bit boundary for filename */ + 848 num_sample_id_bits * sizeof(u64); 849 // clang-format on 850 struct mmap_event written_mmap_event = { 851 .header = 852 { 853 .type = PERF_RECORD_MMAP, 854 .misc = 0, 855 .size = mmap_event_size, 856 }, 857 .pid = 0x68d, 858 .tid = 0x68d, 859 .start = 0x1d000, 860 .len = 0x1000, 861 .pgoff = 0, 862 // .filename = ..., // written separately 863 }; 864 const char mmap_filename[10 + 6] = "/dev/zero"; 865 const u64 mmap_sample_id[] = { 866 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid) 867 1415911367 * 1000000000ULL, // TIME 868 401, // ID 869 2, // STREAM_ID 870 9, // CPU 871 }; 872 const size_t pre_mmap_offset = input.tellp(); 873 input.write(reinterpret_cast<const char*>(&written_mmap_event), 874 offsetof(struct mmap_event, filename)); 875 input.write(mmap_filename, 10 + 6); 876 input.write(reinterpret_cast<const char*>(mmap_sample_id), 877 sizeof(mmap_sample_id)); 878 const size_t written_mmap_size = 879 static_cast<size_t>(input.tellp()) - pre_mmap_offset; 880 ASSERT_EQ(written_mmap_event.header.size, 881 static_cast<u64>(written_mmap_size)); 882 883 // 884 // Parse input. 885 // 886 887 PerfReader pr1; 888 ASSERT_TRUE(pr1.ReadFromString(input.str())); 889 // Write it out and read it in again, the two should have the same data. 890 std::vector<char> output_perf_data; 891 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 892 PerfReader pr2; 893 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 894 895 // Test both versions: 896 for (PerfReader* pr : {&pr1, &pr2}) { 897 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 898 EXPECT_EQ(2, pr->events().size()); 899 900 { 901 const PerfEvent& event = pr->events().Get(0); 902 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 903 904 const SampleEvent& sample = event.sample_event(); 905 EXPECT_EQ(0xffffffff01234567, sample.ip()); 906 EXPECT_EQ(0x68d, sample.pid()); 907 EXPECT_EQ(0x68e, sample.tid()); 908 EXPECT_EQ(1415837014 * 1000000000ULL, sample.sample_time_ns()); 909 EXPECT_EQ(0x00007f999c38d15a, sample.addr()); 910 EXPECT_EQ(401, sample.id()); 911 EXPECT_EQ(1, sample.stream_id()); 912 EXPECT_EQ(8, sample.cpu()); 913 EXPECT_EQ(10001, sample.period()); 914 } 915 916 { 917 const PerfEvent& event = pr->events().Get(1); 918 EXPECT_EQ(PERF_RECORD_MMAP, event.header().type()); 919 920 const SampleInfo& sample = event.mmap_event().sample_info(); 921 EXPECT_EQ(0x68d, sample.pid()); 922 EXPECT_EQ(0x68e, sample.tid()); 923 EXPECT_EQ(1415911367 * 1000000000ULL, sample.sample_time_ns()); 924 EXPECT_EQ(401, sample.id()); 925 EXPECT_EQ(2, sample.stream_id()); 926 EXPECT_EQ(9, sample.cpu()); 927 } 928 } 929 } 930 931 // Test that PERF_SAMPLE_IDENTIFIER is parsed correctly. This field 932 // is in a different place in PERF_RECORD_SAMPLE events compared to the 933 // struct sample_id placed at the end of all other events. 934 TEST(PerfReaderTest, ReadsAndWritesPerfSampleIdentifier) { 935 std::stringstream input; 936 937 // header 938 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 939 940 // data 941 942 // PERF_RECORD_HEADER_ATTR 943 testing::ExamplePerfEventAttrEvent_Hardware( 944 PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP | PERF_SAMPLE_TID, 945 true /*sample_id_all*/) 946 .WithIds({0xdeadbeef, 0xf00dbaad}) 947 .WriteTo(&input); 948 949 // PERF_RECORD_SAMPLE 950 const sample_event written_sample_event = { 951 .header = { 952 .type = PERF_RECORD_SAMPLE, 953 .misc = PERF_RECORD_MISC_KERNEL, 954 .size = sizeof(struct sample_event) + 3 * sizeof(u64), 955 }}; 956 const u64 sample_event_array[] = { 957 0x00000000deadbeef, // IDENTIFIER 958 0x00007f999c38d15a, // IP 959 0x0000068d0000068d, // TID (u32 pid, tid) 960 }; 961 ASSERT_EQ(written_sample_event.header.size, 962 sizeof(written_sample_event.header) + sizeof(sample_event_array)); 963 input.write(reinterpret_cast<const char*>(&written_sample_event), 964 sizeof(written_sample_event)); 965 input.write(reinterpret_cast<const char*>(sample_event_array), 966 sizeof(sample_event_array)); 967 968 // PERF_RECORD_MMAP 969 ASSERT_EQ(40, offsetof(struct mmap_event, filename)); 970 // clang-format off 971 const size_t mmap_event_size = 972 offsetof(struct mmap_event, filename) + 10 + 973 6 /* ==16, nearest 64-bit boundary for filename */ + 2 * sizeof(u64); 974 // clang-format on 975 struct mmap_event written_mmap_event = { 976 .header = 977 { 978 .type = PERF_RECORD_MMAP, 979 .misc = 0, 980 .size = mmap_event_size, 981 }, 982 .pid = 0x68d, 983 .tid = 0x68d, 984 .start = 0x1d000, 985 .len = 0x1000, 986 .pgoff = 0, 987 // .filename = ..., // written separately 988 }; 989 const char mmap_filename[10 + 6] = "/dev/zero"; 990 const u64 mmap_sample_id[] = { 991 // NB: PERF_SAMPLE_IP is not part of sample_id 992 0x0000068d0000068d, // TID (u32 pid, tid) 993 0x00000000f00dbaad, // IDENTIFIER 994 }; 995 const size_t pre_mmap_offset = input.tellp(); 996 input.write(reinterpret_cast<const char*>(&written_mmap_event), 997 offsetof(struct mmap_event, filename)); 998 input.write(mmap_filename, 10 + 6); 999 input.write(reinterpret_cast<const char*>(mmap_sample_id), 1000 sizeof(mmap_sample_id)); 1001 const size_t written_mmap_size = 1002 static_cast<size_t>(input.tellp()) - pre_mmap_offset; 1003 ASSERT_EQ(written_mmap_event.header.size, 1004 static_cast<u64>(written_mmap_size)); 1005 1006 // 1007 // Parse input. 1008 // 1009 1010 PerfReader pr1; 1011 ASSERT_TRUE(pr1.ReadFromString(input.str())); 1012 // Write it out and read it in again, the two should have the same data. 1013 std::vector<char> output_perf_data; 1014 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 1015 PerfReader pr2; 1016 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 1017 1018 // Test both versions: 1019 for (PerfReader* pr : {&pr1, &pr2}) { 1020 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 1021 EXPECT_EQ(2, pr->events().size()); 1022 1023 const PerfEvent& ip_event = pr->events().Get(0); 1024 EXPECT_EQ(PERF_RECORD_SAMPLE, ip_event.header().type()); 1025 EXPECT_EQ(0xdeadbeefULL, ip_event.sample_event().id()); 1026 1027 const PerfEvent& mmap_event = pr->events().Get(1); 1028 EXPECT_EQ(PERF_RECORD_MMAP, mmap_event.header().type()); 1029 EXPECT_EQ(0xf00dbaadULL, mmap_event.mmap_event().sample_info().id()); 1030 } 1031 } 1032 1033 TEST(PerfReaderTest, ReadsAndWritesMmap2Events) { 1034 std::stringstream input; 1035 1036 // header 1037 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 1038 1039 // data 1040 1041 // PERF_RECORD_HEADER_ATTR 1042 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP, 1043 false /*sample_id_all*/) 1044 .WriteTo(&input); 1045 1046 // PERF_RECORD_MMAP2 1047 ASSERT_EQ(72, offsetof(struct mmap2_event, filename)); 1048 // clang-format off 1049 const size_t mmap_event_size = 1050 offsetof(struct mmap2_event, filename) + 10 + 1051 6; /* ==16, nearest 64-bit boundary for filename */ 1052 // clang-format on 1053 struct mmap2_event written_mmap_event = { 1054 .header = 1055 { 1056 .type = PERF_RECORD_MMAP2, 1057 .misc = 0, 1058 .size = mmap_event_size, 1059 }, 1060 .pid = 0x68d, 1061 .tid = 0x68d, 1062 .start = 0x1d000, 1063 .len = 0x1000, 1064 .pgoff = 0x2000, 1065 .maj = 6, 1066 .min = 7, 1067 .ino = 8, 1068 .ino_generation = 9, 1069 .prot = 1 | 2, // == PROT_READ | PROT_WRITE 1070 .flags = 2, // == MAP_PRIVATE 1071 // .filename = ..., // written separately 1072 }; 1073 const char mmap_filename[10 + 6] = "/dev/zero"; 1074 const size_t pre_mmap_offset = input.tellp(); 1075 input.write(reinterpret_cast<const char*>(&written_mmap_event), 1076 offsetof(struct mmap2_event, filename)); 1077 input.write(mmap_filename, 10 + 6); 1078 const size_t written_mmap_size = 1079 static_cast<size_t>(input.tellp()) - pre_mmap_offset; 1080 ASSERT_EQ(written_mmap_event.header.size, 1081 static_cast<u64>(written_mmap_size)); 1082 1083 // 1084 // Parse input. 1085 // 1086 1087 PerfReader pr1; 1088 ASSERT_TRUE(pr1.ReadFromString(input.str())); 1089 // Write it out and read it in again, the two should have the same data. 1090 std::vector<char> output_perf_data; 1091 ASSERT_TRUE(pr1.WriteToVector(&output_perf_data)); 1092 PerfReader pr2; 1093 ASSERT_TRUE(pr2.ReadFromVector(output_perf_data)); 1094 1095 // Test both versions: 1096 for (PerfReader* pr : {&pr1, &pr2}) { 1097 // PERF_RECORD_HEADER_ATTR is added to attr(), not events(). 1098 EXPECT_EQ(1, pr->events().size()); 1099 1100 const PerfEvent& event = pr->events().Get(0); 1101 EXPECT_EQ(PERF_RECORD_MMAP2, event.header().type()); 1102 EXPECT_EQ(0x68d, event.mmap_event().pid()); 1103 EXPECT_EQ(0x68d, event.mmap_event().tid()); 1104 EXPECT_EQ(0x1d000, event.mmap_event().start()); 1105 EXPECT_EQ(0x1000, event.mmap_event().len()); 1106 EXPECT_EQ(0x2000, event.mmap_event().pgoff()); 1107 EXPECT_EQ(6, event.mmap_event().maj()); 1108 EXPECT_EQ(7, event.mmap_event().min()); 1109 EXPECT_EQ(8, event.mmap_event().ino()); 1110 EXPECT_EQ(9, event.mmap_event().ino_generation()); 1111 EXPECT_EQ(1 | 2, event.mmap_event().prot()); 1112 EXPECT_EQ(2, event.mmap_event().flags()); 1113 } 1114 } 1115 1116 // Regression test for http://crbug.com/493533 1117 TEST(PerfReaderTest, ReadsAllAvailableMetadataTypes) { 1118 std::stringstream input; 1119 1120 const uint32_t features = (1 << HEADER_HOSTNAME) | (1 << HEADER_OSRELEASE) | 1121 (1 << HEADER_VERSION) | (1 << HEADER_ARCH) | 1122 (1 << HEADER_LAST_FEATURE); 1123 1124 // header 1125 testing::ExamplePerfDataFileHeader file_header(features); 1126 file_header.WriteTo(&input); 1127 1128 // metadata 1129 1130 size_t metadata_offset = 1131 file_header.data_end() + 5 * sizeof(perf_file_section); 1132 1133 // HEADER_HOSTNAME 1134 testing::ExampleStringMetadata hostname_metadata("hostname", metadata_offset); 1135 metadata_offset += hostname_metadata.size(); 1136 1137 // HEADER_OSRELEASE 1138 testing::ExampleStringMetadata osrelease_metadata("osrelease", 1139 metadata_offset); 1140 metadata_offset += osrelease_metadata.size(); 1141 1142 // HEADER_VERSION 1143 testing::ExampleStringMetadata version_metadata("version", metadata_offset); 1144 metadata_offset += version_metadata.size(); 1145 1146 // HEADER_ARCH 1147 testing::ExampleStringMetadata arch_metadata("arch", metadata_offset); 1148 metadata_offset += arch_metadata.size(); 1149 1150 // HEADER_LAST_FEATURE -- this is just a dummy metadata that will be skipped 1151 // over. In practice, there will not actually be a metadata entry of type 1152 // HEADER_LAST_FEATURE. But use because it will never become a supported 1153 // metadata type. 1154 testing::ExampleStringMetadata last_feature("*unsupported*", metadata_offset); 1155 metadata_offset += last_feature.size(); 1156 1157 hostname_metadata.index_entry().WriteTo(&input); 1158 osrelease_metadata.index_entry().WriteTo(&input); 1159 version_metadata.index_entry().WriteTo(&input); 1160 arch_metadata.index_entry().WriteTo(&input); 1161 last_feature.index_entry().WriteTo(&input); 1162 1163 hostname_metadata.WriteTo(&input); 1164 osrelease_metadata.WriteTo(&input); 1165 version_metadata.WriteTo(&input); 1166 arch_metadata.WriteTo(&input); 1167 last_feature.WriteTo(&input); 1168 1169 // 1170 // Parse input. 1171 // 1172 1173 PerfReader pr; 1174 ASSERT_TRUE(pr.ReadFromString(input.str())); 1175 1176 // The dummy metadata should not have prevented the reading of the other 1177 // metadata. 1178 const auto& string_metadata = pr.string_metadata(); 1179 EXPECT_EQ("hostname", string_metadata.hostname().value()); 1180 EXPECT_EQ("osrelease", string_metadata.kernel_version().value()); 1181 EXPECT_EQ("version", string_metadata.perf_version().value()); 1182 EXPECT_EQ("arch", string_metadata.architecture().value()); 1183 } 1184 1185 TEST(PerfReaderTest, AttrsWithDifferentSampleTypes) { 1186 std::stringstream input; 1187 1188 // PERF_RECORD_SAMPLE 1189 testing::ExamplePerfSampleEvent sample_event_1( 1190 testing::SampleInfo().Id(51).Ip(0x00000000002c100a).Tid(1002)); 1191 // PERF_RECORD_SAMPLE 1192 testing::ExamplePerfSampleEvent sample_event_2(testing::SampleInfo() 1193 .Id(61) 1194 .Ip(0x00000000002c100b) 1195 .Tid(1002) 1196 .Time(1000006)); 1197 // PERF_RECORD_SAMPLE 1198 testing::ExamplePerfSampleEvent sample_event_3( 1199 testing::SampleInfo().Id(52).Ip(0x00000000002c100c).Tid(1002)); 1200 1201 const size_t data_size = sample_event_1.GetSize() + sample_event_2.GetSize() + 1202 sample_event_3.GetSize(); 1203 const uint32_t features = 0; 1204 1205 // header 1206 testing::ExamplePerfDataFileHeader file_header(features); 1207 file_header.WithAttrIdsCount(3).WithAttrCount(2).WithDataSize(data_size); 1208 file_header.WriteTo(&input); 1209 1210 // attr ids 1211 testing::AttrIdsSection attr_ids(input.tellp()); 1212 const auto id_section_1 = attr_ids.AddIds({51, 52}); 1213 const auto id_section_2 = attr_ids.AddIds({61}); 1214 attr_ids.WriteTo(&input); 1215 1216 // attrs 1217 ASSERT_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 1218 testing::ExamplePerfFileAttr_Hardware( 1219 PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1220 true /*sample_id_all*/) 1221 .WithIds(id_section_1) 1222 .WriteTo(&input); 1223 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IDENTIFIER | 1224 PERF_SAMPLE_IP | PERF_SAMPLE_TID | 1225 PERF_SAMPLE_TIME, 1226 true /*sample_id_all*/) 1227 .WithIds(id_section_2) 1228 .WriteTo(&input); 1229 1230 // data 1231 1232 ASSERT_EQ(file_header.header().data.offset, static_cast<u64>(input.tellp())); 1233 sample_event_1.WriteTo(&input); 1234 sample_event_2.WriteTo(&input); 1235 sample_event_3.WriteTo(&input); 1236 ASSERT_EQ(file_header.header().data.offset + data_size, 1237 static_cast<u64>(input.tellp())); 1238 1239 // no metadata 1240 1241 // 1242 // Parse input. 1243 // 1244 PerfReader pr; 1245 ASSERT_TRUE(pr.ReadFromString(input.str())); 1246 1247 // Make sure the attr ids were read correctly. 1248 ASSERT_EQ(2, pr.attrs().size()); 1249 ASSERT_EQ(2, pr.attrs().Get(0).ids().size()); 1250 EXPECT_EQ(51, pr.attrs().Get(0).ids(0)); 1251 EXPECT_EQ(52, pr.attrs().Get(0).ids(1)); 1252 ASSERT_EQ(1, pr.attrs().Get(1).ids().size()); 1253 EXPECT_EQ(61, pr.attrs().Get(1).ids(0)); 1254 1255 // Verify events were read properly. 1256 ASSERT_EQ(3, pr.events().size()); 1257 { 1258 const PerfEvent& event = pr.events().Get(0); 1259 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1260 1261 const SampleEvent& sample = event.sample_event(); 1262 EXPECT_EQ(51, sample.id()); 1263 EXPECT_EQ(0x00000000002c100a, sample.ip()); 1264 EXPECT_EQ(1002, sample.tid()); 1265 // This event doesn't have a timestamp. 1266 EXPECT_FALSE(sample.has_sample_time_ns()); 1267 } 1268 { 1269 const PerfEvent& event = pr.events().Get(1); 1270 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1271 1272 const SampleEvent& sample = event.sample_event(); 1273 EXPECT_EQ(61, sample.id()); 1274 EXPECT_EQ(0x00000000002c100b, sample.ip()); 1275 EXPECT_EQ(1002, sample.tid()); 1276 EXPECT_EQ(1000006, sample.sample_time_ns()); 1277 } 1278 { 1279 const PerfEvent& event = pr.events().Get(2); 1280 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1281 1282 const SampleEvent& sample = event.sample_event(); 1283 EXPECT_EQ(52, sample.id()); 1284 EXPECT_EQ(0x00000000002c100c, sample.ip()); 1285 EXPECT_EQ(1002, sample.tid()); 1286 // This event doesn't have a timestamp. 1287 EXPECT_FALSE(sample.has_sample_time_ns()); 1288 } 1289 } 1290 1291 // Neither PERF_SAMPLE_ID nor PERF_SAMPLE_IDENTIFIER are set. We should 1292 // fall back to using the first attr when looking for the sample_format. 1293 TEST(PerfReaderTest, NoSampleIdField) { 1294 std::stringstream input; 1295 1296 // PERF_RECORD_SAMPLE 1297 testing::ExamplePerfSampleEvent sample_event( 1298 testing::SampleInfo().Ip(0x00000000002c100a).Tid(1002)); 1299 1300 const size_t data_size = sample_event.GetSize(); 1301 const uint32_t features = 0; 1302 1303 // header 1304 testing::ExamplePerfDataFileHeader file_header(features); 1305 file_header.WithAttrCount(1).WithDataSize(data_size); 1306 file_header.WriteTo(&input); 1307 1308 // attrs 1309 ASSERT_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 1310 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1311 false /*sample_id_all*/) 1312 .WithConfig(456) 1313 .WriteTo(&input); 1314 1315 // data 1316 1317 ASSERT_EQ(file_header.header().data.offset, static_cast<u64>(input.tellp())); 1318 sample_event.WriteTo(&input); 1319 ASSERT_EQ(file_header.header().data.offset + data_size, 1320 static_cast<u64>(input.tellp())); 1321 1322 // no metadata 1323 1324 // 1325 // Parse input. 1326 // 1327 1328 PerfReader pr; 1329 ASSERT_TRUE(pr.ReadFromString(input.str())); 1330 1331 // Make sure the attr was recorded properly. 1332 ASSERT_EQ(1, pr.attrs().size()); 1333 EXPECT_EQ(456, pr.attrs().Get(0).attr().config()); 1334 1335 // Verify subsequent sample event was read properly. 1336 ASSERT_EQ(1, pr.events().size()); 1337 const PerfEvent& event = pr.events().Get(0); 1338 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1339 EXPECT_EQ(data_size, event.header().size()); 1340 1341 EXPECT_EQ(0x00000000002c100a, event.sample_event().ip()); 1342 EXPECT_EQ(1002, event.sample_event().tid()); 1343 } 1344 1345 // When sample_id_all == false, non-sample events should not look for sample_id. 1346 TEST(PerfReaderTest, SampleIdFalseMeansDontReadASampleId) { 1347 std::stringstream input; 1348 1349 // PERF_RECORD_SAMPLE 1350 testing::ExamplePerfSampleEvent sample_event( 1351 testing::SampleInfo().Ip(0x00000000002c100a).Tid(1002).Id(48)); 1352 1353 // PERF_RECORD_MMAP 1354 testing::ExampleMmapEvent mmap_event( 1355 1001, 0x1c1000, 0x1000, 0, "/usr/lib/foo.so", 1356 // Write a sample_info even though we shouldn't (sample_id_all==false) 1357 // Use a bogus ID: if we look at the sample_id and look for an attr, it 1358 // should return an error. 1359 testing::SampleInfo().Tid(1001).Id(666)); 1360 1361 const size_t data_size = sample_event.GetSize() + mmap_event.GetSize(); 1362 const uint32_t features = 0; 1363 1364 // header 1365 testing::ExamplePerfDataFileHeader file_header(features); 1366 file_header.WithAttrIdsCount(1).WithAttrCount(1).WithDataSize(data_size); 1367 file_header.WriteTo(&input); 1368 1369 // attr IDs 1370 testing::AttrIdsSection attr_ids(input.tellp()); 1371 const auto id_section = attr_ids.AddId(48); 1372 attr_ids.WriteTo(&input); 1373 1374 // attrs 1375 ASSERT_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 1376 testing::ExamplePerfFileAttr_Hardware( 1377 PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_ID, 1378 false /*sample_id_all*/) 1379 .WithIds(id_section) 1380 .WriteTo(&input); 1381 1382 // data 1383 1384 ASSERT_EQ(file_header.header().data.offset, static_cast<u64>(input.tellp())); 1385 sample_event.WriteTo(&input); 1386 mmap_event.WriteTo(&input); 1387 ASSERT_EQ(file_header.header().data.offset + data_size, 1388 static_cast<u64>(input.tellp())); 1389 1390 // no metadata 1391 1392 // 1393 // Parse input. 1394 // 1395 1396 PerfReader pr; 1397 EXPECT_TRUE(pr.ReadFromString(input.str())); 1398 1399 // Verify events were read properly. 1400 ASSERT_EQ(2, pr.events().size()); 1401 { 1402 const PerfEvent& event = pr.events().Get(0); 1403 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1404 1405 EXPECT_EQ(0x00000000002c100a, event.sample_event().ip()); 1406 EXPECT_EQ(1002, event.sample_event().tid()); 1407 EXPECT_EQ(48, event.sample_event().id()); 1408 } 1409 1410 { 1411 const PerfEvent& event = pr.events().Get(1); 1412 EXPECT_EQ(PERF_RECORD_MMAP, event.header().type()); 1413 1414 // This event is malformed: it has junk at the end. Therefore, sample_info 1415 // should not have TID or ID fields. 1416 EXPECT_FALSE(event.mmap_event().sample_info().has_tid()); 1417 EXPECT_FALSE(event.mmap_event().sample_info().has_id()); 1418 } 1419 } 1420 1421 // Regression test for http://crbug.com/496441 1422 TEST(PerfReaderTest, LargePerfEventAttr) { 1423 std::stringstream input; 1424 1425 const size_t attr_size = sizeof(perf_event_attr) + sizeof(u64); 1426 testing::ExamplePerfSampleEvent sample_event( 1427 testing::SampleInfo().Ip(0x00000000002c100a).Tid(1002)); 1428 const size_t data_size = sample_event.GetSize(); 1429 1430 // header 1431 testing::ExamplePerfDataFileHeader file_header(0); 1432 file_header.WithCustomPerfEventAttrSize(attr_size) 1433 .WithAttrCount(1) 1434 .WithDataSize(data_size); 1435 file_header.WriteTo(&input); 1436 1437 // attrs 1438 ASSERT_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 1439 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1440 false /*sample_id_all*/) 1441 .WithAttrSize(attr_size) 1442 .WithConfig(456) 1443 .WriteTo(&input); 1444 1445 // data 1446 1447 ASSERT_EQ(file_header.header().data.offset, static_cast<u64>(input.tellp())); 1448 sample_event.WriteTo(&input); 1449 ASSERT_EQ(file_header.header().data.offset + data_size, 1450 static_cast<u64>(input.tellp())); 1451 1452 // no metadata 1453 1454 // 1455 // Parse input. 1456 // 1457 1458 PerfReader pr; 1459 ASSERT_TRUE(pr.ReadFromString(input.str())); 1460 1461 // Make sure the attr was recorded properly. 1462 EXPECT_EQ(1, pr.attrs().size()); 1463 EXPECT_EQ(456, pr.attrs().Get(0).attr().config()); 1464 1465 // Verify subsequent sample event was read properly. 1466 ASSERT_EQ(1, pr.events().size()); 1467 1468 const PerfEvent& event = pr.events().Get(0); 1469 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1470 EXPECT_EQ(data_size, event.header().size()); 1471 1472 const SampleEvent& sample_info = event.sample_event(); 1473 EXPECT_EQ(0x00000000002c100a, sample_info.ip()); 1474 EXPECT_EQ(1002, sample_info.tid()); 1475 } 1476 1477 // Regression test for http://crbug.com/496441 1478 TEST(PerfReaderTest, LargePerfEventAttrPiped) { 1479 std::stringstream input; 1480 1481 // pipe header 1482 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 1483 1484 // data 1485 1486 // PERF_RECORD_HEADER_ATTR 1487 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1488 true /*sample_id_all*/) 1489 .WithAttrSize(sizeof(perf_event_attr) + sizeof(u64)) 1490 .WithConfig(123) 1491 .WriteTo(&input); 1492 1493 // PERF_RECORD_HEADER_EVENT_TYPE 1494 const struct event_type_event event_type = { 1495 .header = 1496 { 1497 .type = PERF_RECORD_HEADER_EVENT_TYPE, 1498 .misc = 0, 1499 .size = sizeof(struct event_type_event), 1500 }, 1501 .event_type = { 1502 /*event_id*/ 123, 1503 /*name*/ "cycles", 1504 }, 1505 }; 1506 input.write(reinterpret_cast<const char*>(&event_type), sizeof(event_type)); 1507 1508 testing::ExamplePerfSampleEvent sample_event( 1509 testing::SampleInfo().Ip(0x00000000002c100a).Tid(1002)); 1510 sample_event.WriteTo(&input); 1511 1512 // 1513 // Parse input. 1514 // 1515 1516 PerfReader pr; 1517 ASSERT_TRUE(pr.ReadFromString(input.str())); 1518 1519 // Make sure the attr was recorded properly. 1520 EXPECT_EQ(1, pr.attrs().size()); 1521 EXPECT_EQ(123, pr.attrs().Get(0).attr().config()); 1522 ASSERT_EQ(1, pr.event_types().size()); 1523 EXPECT_EQ("cycles", pr.event_types().Get(0).name()); 1524 1525 // Verify subsequent sample event was read properly. 1526 ASSERT_EQ(1, pr.events().size()); 1527 1528 const PerfEvent& event = pr.events().Get(0); 1529 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1530 EXPECT_EQ(sample_event.GetSize(), event.header().size()); 1531 1532 const SampleEvent& sample_info = event.sample_event(); 1533 EXPECT_EQ(0x00000000002c100a, sample_info.ip()); 1534 EXPECT_EQ(1002, sample_info.tid()); 1535 } 1536 1537 // Regression test for http://crbug.com/496441 1538 TEST(PerfReaderTest, SmallPerfEventAttr) { 1539 std::stringstream input; 1540 1541 const size_t attr_size = sizeof(perf_event_attr) - sizeof(u64); 1542 testing::ExamplePerfSampleEvent sample_event( 1543 testing::SampleInfo().Ip(0x00000000002c100a).Tid(1002)); 1544 const size_t data_size = sample_event.GetSize(); 1545 1546 // header 1547 testing::ExamplePerfDataFileHeader file_header(0); 1548 file_header.WithCustomPerfEventAttrSize(attr_size) 1549 .WithAttrCount(1) 1550 .WithDataSize(data_size); 1551 file_header.WriteTo(&input); 1552 1553 // attrs 1554 CHECK_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 1555 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1556 false /*sample_id_all*/) 1557 .WithAttrSize(attr_size) 1558 .WithConfig(456) 1559 .WriteTo(&input); 1560 1561 // data 1562 1563 ASSERT_EQ(file_header.header().data.offset, static_cast<u64>(input.tellp())); 1564 sample_event.WriteTo(&input); 1565 ASSERT_EQ(file_header.header().data.offset + data_size, 1566 static_cast<u64>(input.tellp())); 1567 1568 // no metadata 1569 1570 // 1571 // Parse input. 1572 // 1573 1574 PerfReader pr; 1575 ASSERT_TRUE(pr.ReadFromString(input.str())); 1576 1577 // Make sure the attr was recorded properly. 1578 EXPECT_EQ(1, pr.attrs().size()); 1579 EXPECT_EQ(456, pr.attrs().Get(0).attr().config()); 1580 1581 // Verify subsequent sample event was read properly. 1582 ASSERT_EQ(1, pr.events().size()); 1583 1584 const PerfEvent& event = pr.events().Get(0); 1585 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1586 EXPECT_EQ(data_size, event.header().size()); 1587 1588 const SampleEvent& sample_info = event.sample_event(); 1589 EXPECT_EQ(0x00000000002c100a, sample_info.ip()); 1590 EXPECT_EQ(1002, sample_info.tid()); 1591 } 1592 1593 // Regression test for http://crbug.com/496441 1594 TEST(PerfReaderTest, SmallPerfEventAttrPiped) { 1595 std::stringstream input; 1596 1597 // pipe header 1598 testing::ExamplePipedPerfDataFileHeader().WriteTo(&input); 1599 1600 // data 1601 1602 // PERF_RECORD_HEADER_ATTR 1603 testing::ExamplePerfEventAttrEvent_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1604 true /*sample_id_all*/) 1605 .WithAttrSize(sizeof(perf_event_attr) - sizeof(u64)) 1606 .WithConfig(123) 1607 .WriteTo(&input); 1608 1609 // PERF_RECORD_HEADER_EVENT_TYPE 1610 const struct event_type_event event_type = { 1611 .header = 1612 { 1613 .type = PERF_RECORD_HEADER_EVENT_TYPE, 1614 .misc = 0, 1615 .size = sizeof(struct event_type_event), 1616 }, 1617 .event_type = { 1618 /*event_id*/ 123, 1619 /*name*/ "cycles", 1620 }, 1621 }; 1622 input.write(reinterpret_cast<const char*>(&event_type), sizeof(event_type)); 1623 1624 testing::ExamplePerfSampleEvent sample_event( 1625 testing::SampleInfo().Ip(0x00000000002c100a).Tid(1002)); 1626 sample_event.WriteTo(&input); 1627 1628 // 1629 // Parse input. 1630 // 1631 1632 PerfReader pr; 1633 ASSERT_TRUE(pr.ReadFromString(input.str())); 1634 1635 // Make sure the attr was recorded properly. 1636 EXPECT_EQ(1, pr.attrs().size()); 1637 EXPECT_EQ(123, pr.attrs().Get(0).attr().config()); 1638 ASSERT_EQ(1, pr.event_types().size()); 1639 EXPECT_EQ("cycles", pr.event_types().Get(0).name()); 1640 1641 // Verify subsequent sample event was read properly. 1642 ASSERT_EQ(1, pr.events().size()); 1643 1644 const PerfEvent& event = pr.events().Get(0); 1645 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1646 EXPECT_EQ(sample_event.GetSize(), event.header().size()); 1647 1648 const SampleEvent& sample_info = event.sample_event(); 1649 EXPECT_EQ(0x00000000002c100a, sample_info.ip()); 1650 EXPECT_EQ(1002, sample_info.tid()); 1651 } 1652 1653 TEST(PerfReaderTest, CrossEndianAttrs) { 1654 for (bool is_cross_endian : {true, false}) { 1655 LOG(INFO) << "Testing with cross endianness = " << is_cross_endian; 1656 1657 std::stringstream input; 1658 1659 // header 1660 const uint32_t features = 0; 1661 testing::ExamplePerfDataFileHeader file_header(features); 1662 file_header.WithAttrCount(3) 1663 .WithCrossEndianness(is_cross_endian) 1664 .WriteTo(&input); 1665 1666 // attrs 1667 CHECK_EQ(file_header.header().attrs.offset, 1668 static_cast<u64>(input.tellp())); 1669 // Provide two attrs with different sample_id_all values to test the 1670 // correctness of byte swapping of the bit fields. 1671 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1672 true /*sample_id_all*/) 1673 .WithConfig(123) 1674 .WithCrossEndianness(is_cross_endian) 1675 .WriteTo(&input); 1676 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1677 true /*sample_id_all*/) 1678 .WithConfig(456) 1679 .WithCrossEndianness(is_cross_endian) 1680 .WriteTo(&input); 1681 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1682 false /*sample_id_all*/) 1683 .WithConfig(456) 1684 .WithCrossEndianness(is_cross_endian) 1685 .WriteTo(&input); 1686 1687 // No data. 1688 // No metadata. 1689 1690 // Read data. 1691 1692 PerfReader pr; 1693 ASSERT_TRUE(pr.ReadFromString(input.str())); 1694 1695 // Make sure the attr was recorded properly. 1696 EXPECT_EQ(3, pr.attrs().size()); 1697 1698 const auto& attr0 = pr.attrs().Get(0).attr(); 1699 EXPECT_EQ(123, attr0.config()); 1700 EXPECT_EQ(1, attr0.sample_period()); 1701 EXPECT_EQ(PERF_SAMPLE_IP | PERF_SAMPLE_TID, attr0.sample_type()); 1702 EXPECT_TRUE(attr0.sample_id_all()); 1703 EXPECT_EQ(2, attr0.precise_ip()); 1704 1705 const auto& attr1 = pr.attrs().Get(1).attr(); 1706 EXPECT_EQ(456, attr1.config()); 1707 EXPECT_EQ(1, attr1.sample_period()); 1708 EXPECT_EQ(PERF_SAMPLE_IP | PERF_SAMPLE_TID, attr1.sample_type()); 1709 EXPECT_TRUE(attr1.sample_id_all()); 1710 EXPECT_EQ(2, attr1.precise_ip()); 1711 1712 const auto& attr2 = pr.attrs().Get(2).attr(); 1713 EXPECT_EQ(456, attr2.config()); 1714 EXPECT_EQ(1, attr2.sample_period()); 1715 EXPECT_EQ(PERF_SAMPLE_IP | PERF_SAMPLE_TID, attr2.sample_type()); 1716 EXPECT_FALSE(attr2.sample_id_all()); 1717 EXPECT_EQ(2, attr2.precise_ip()); 1718 } 1719 } 1720 1721 TEST(PerfReaderTest, CrossEndianNormalPerfData) { 1722 // data 1723 // Do this before header to compute the total data size. 1724 std::stringstream input_data; 1725 testing::ExampleMmapEvent( 1726 1234, 0x0000000000810000, 0x10000, 0x2000, "/usr/lib/foo.so", 1727 testing::SampleInfo().Tid(bswap_32(1234), bswap_32(1235))) 1728 .WithCrossEndianness(true) 1729 .WriteTo(&input_data); 1730 testing::ExampleForkEvent( 1731 1236, 1234, 1237, 1235, 30ULL * 1000000000, 1732 testing::SampleInfo().Tid(bswap_32(1236), bswap_32(1237))) 1733 .WithCrossEndianness(true) 1734 .WriteTo(&input_data); 1735 testing::ExamplePerfSampleEvent(testing::SampleInfo() 1736 .Ip(bswap_64(0x0000000000810100)) 1737 .Tid(bswap_32(1234), bswap_32(1235))) 1738 .WithCrossEndianness(true) 1739 .WriteTo(&input_data); 1740 testing::ExamplePerfSampleEvent(testing::SampleInfo() 1741 .Ip(bswap_64(0x000000000081ff00)) 1742 .Tid(bswap_32(1236), bswap_32(1237))) 1743 .WithCrossEndianness(true) 1744 .WriteTo(&input_data); 1745 1746 std::stringstream input; 1747 1748 // header 1749 const size_t data_size = input_data.str().size(); 1750 const uint32_t features = (1 << HEADER_HOSTNAME) | (1 << HEADER_OSRELEASE); 1751 testing::ExamplePerfDataFileHeader file_header(features); 1752 file_header.WithAttrCount(1) 1753 .WithDataSize(data_size) 1754 .WithCrossEndianness(true) 1755 .WriteTo(&input); 1756 1757 // attrs 1758 CHECK_EQ(file_header.header().attrs.offset, static_cast<u64>(input.tellp())); 1759 testing::ExamplePerfFileAttr_Hardware(PERF_SAMPLE_IP | PERF_SAMPLE_TID, 1760 true /*sample_id_all*/) 1761 .WithConfig(456) 1762 .WithCrossEndianness(true) 1763 .WriteTo(&input); 1764 1765 // Write data. 1766 1767 u64 data_offset = file_header.header().data.offset; 1768 ASSERT_EQ(data_offset, static_cast<u64>(input.tellp())); 1769 input << input_data.str(); 1770 ASSERT_EQ(data_offset + data_size, static_cast<u64>(input.tellp())); 1771 1772 // metadata 1773 size_t metadata_offset = 1774 file_header.data_end() + 2 * sizeof(perf_file_section); 1775 1776 // HEADER_HOSTNAME 1777 testing::ExampleStringMetadata hostname_metadata("hostname", metadata_offset); 1778 hostname_metadata.WithCrossEndianness(true); 1779 metadata_offset += hostname_metadata.size(); 1780 1781 // HEADER_OSRELEASE 1782 testing::ExampleStringMetadata osrelease_metadata("osrelease", 1783 metadata_offset); 1784 osrelease_metadata.WithCrossEndianness(true); 1785 metadata_offset += osrelease_metadata.size(); 1786 1787 hostname_metadata.index_entry().WriteTo(&input); 1788 osrelease_metadata.index_entry().WriteTo(&input); 1789 1790 hostname_metadata.WriteTo(&input); 1791 osrelease_metadata.WriteTo(&input); 1792 1793 // 1794 // Parse input. 1795 // 1796 1797 PerfReader pr; 1798 ASSERT_TRUE(pr.ReadFromString(input.str())); 1799 1800 // Make sure the attr was recorded properly. 1801 EXPECT_EQ(1, pr.attrs().size()); 1802 EXPECT_EQ(456, pr.attrs().Get(0).attr().config()); 1803 EXPECT_TRUE(pr.attrs().Get(0).attr().sample_id_all()); 1804 1805 // Verify perf events. 1806 ASSERT_EQ(4, pr.events().size()); 1807 1808 { 1809 const PerfEvent& event = pr.events().Get(0); 1810 EXPECT_EQ(PERF_RECORD_MMAP, event.header().type()); 1811 EXPECT_EQ(1234, event.mmap_event().pid()); 1812 EXPECT_EQ(1234, event.mmap_event().tid()); 1813 EXPECT_EQ(string("/usr/lib/foo.so"), event.mmap_event().filename()); 1814 EXPECT_EQ(0x0000000000810000, event.mmap_event().start()); 1815 EXPECT_EQ(0x10000, event.mmap_event().len()); 1816 EXPECT_EQ(0x2000, event.mmap_event().pgoff()); 1817 } 1818 1819 { 1820 const PerfEvent& event = pr.events().Get(1); 1821 EXPECT_EQ(PERF_RECORD_FORK, event.header().type()); 1822 EXPECT_EQ(1236, event.fork_event().pid()); 1823 EXPECT_EQ(1234, event.fork_event().ppid()); 1824 EXPECT_EQ(1237, event.fork_event().tid()); 1825 EXPECT_EQ(1235, event.fork_event().ptid()); 1826 EXPECT_EQ(30ULL * 1000000000, event.fork_event().fork_time_ns()); 1827 } 1828 1829 { 1830 const PerfEvent& event = pr.events().Get(2); 1831 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1832 1833 const SampleEvent& sample_info = event.sample_event(); 1834 EXPECT_EQ(0x0000000000810100, sample_info.ip()); 1835 EXPECT_EQ(1234, sample_info.pid()); 1836 EXPECT_EQ(1235, sample_info.tid()); 1837 } 1838 1839 { 1840 const PerfEvent& event = pr.events().Get(3); 1841 EXPECT_EQ(PERF_RECORD_SAMPLE, event.header().type()); 1842 1843 const SampleEvent& sample_info = event.sample_event(); 1844 EXPECT_EQ(0x000000000081ff00, sample_info.ip()); 1845 EXPECT_EQ(1236, sample_info.pid()); 1846 EXPECT_EQ(1237, sample_info.tid()); 1847 } 1848 } 1849 1850 TEST(PerfReaderTest, MetadataMaskInitialized) { 1851 // The metadata mask is actually an array of uint64's. The accessors/mutator 1852 // in PerfReader depend on it being initialized. 1853 PerfReader reader; 1854 ASSERT_EQ(1U, reader.proto().metadata_mask().size()); 1855 EXPECT_EQ(0U, reader.metadata_mask()); 1856 } 1857 1858 } // namespace quipper 1859