Home | History | Annotate | Download | only in quipper
      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