2 * Copyright (C) 2015 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <gtest/gtest.h>
20 #include "environment.h"
21 #include "event_attr.h"
22 #include "event_type.h"
24 #include "record_file.h"
26 #include "record_equal_test.h"
28 using namespace PerfFileFormat;
30 class RecordFileTest : public ::testing::Test {
32 virtual void SetUp() {
33 filename_ = "temporary.record_file";
36 void AddEventType(const std::string& event_type_str) {
37 std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType(event_type_str);
38 ASSERT_TRUE(event_type_modifier != nullptr);
39 perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
40 attrs_.push_back(attr);
42 attr_id.attr = &attrs_[attrs_.size() - 1];
43 attr_id.ids.push_back(attrs_.size()); // Fake id.
44 attr_ids_.push_back(attr_id);
47 std::string filename_;
48 std::vector<perf_event_attr> attrs_;
49 std::vector<AttrWithId> attr_ids_;
52 TEST_F(RecordFileTest, smoke) {
53 // Write to a record file.
54 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(filename_);
55 ASSERT_TRUE(writer != nullptr);
57 // Write attr section.
58 AddEventType("cpu-cycles");
59 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_));
61 // Write data section.
62 MmapRecord mmap_record =
63 CreateMmapRecord(attrs_[0], true, 1, 1, 0x1000, 0x2000, 0x3000, "mmap_record_example");
64 ASSERT_TRUE(writer->WriteData(mmap_record.BinaryFormat()));
66 // Check data section that has been written.
67 std::vector<std::unique_ptr<Record>> records;
68 ASSERT_TRUE(writer->ReadDataSection(&records));
69 ASSERT_EQ(1u, records.size());
70 CheckRecordEqual(mmap_record, *records[0]);
72 // Write feature section.
73 ASSERT_TRUE(writer->WriteFeatureHeader(1));
74 char p[BuildId::Size()];
75 for (size_t i = 0; i < BuildId::Size(); ++i) {
79 BuildIdRecord build_id_record = CreateBuildIdRecord(false, getpid(), build_id, "init");
80 ASSERT_TRUE(writer->WriteBuildIdFeature({build_id_record}));
81 ASSERT_TRUE(writer->Close());
83 // Read from a record file.
84 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(filename_);
85 ASSERT_TRUE(reader != nullptr);
86 const FileHeader* file_header = reader->FileHeader();
87 ASSERT_TRUE(file_header != nullptr);
88 std::vector<const FileAttr*> file_attrs = reader->AttrSection();
89 ASSERT_EQ(1u, file_attrs.size());
90 ASSERT_EQ(0, memcmp(&file_attrs[0]->attr, attr_ids_[0].attr, sizeof(perf_event_attr)));
91 std::vector<uint64_t> ids = reader->IdsForAttr(file_attrs[0]);
92 ASSERT_EQ(ids, attr_ids_[0].ids);
94 // Read and check data section.
95 records = reader->DataSection();
96 ASSERT_EQ(1u, records.size());
97 CheckRecordEqual(mmap_record, *records[0]);
99 // Read and check feature section.
100 ASSERT_TRUE(file_header->features[FEAT_BUILD_ID / 8] & (1 << (FEAT_BUILD_ID % 8)));
101 std::map<int, SectionDesc> sections = reader->FeatureSectionDescriptors();
102 ASSERT_EQ(1u, sections.size());
103 ASSERT_TRUE(sections.find(FEAT_BUILD_ID) != sections.end());
104 const perf_event_header* header = reinterpret_cast<const perf_event_header*>(
105 reader->DataAtOffset(sections[FEAT_BUILD_ID].offset));
106 ASSERT_TRUE(header != nullptr);
107 ASSERT_EQ(sections[FEAT_BUILD_ID].size, header->size);
108 CheckRecordEqual(build_id_record, BuildIdRecord(header));
110 ASSERT_TRUE(reader->Close());
113 TEST_F(RecordFileTest, records_sorted_by_time) {
114 // Write to a record file.
115 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(filename_);
116 ASSERT_TRUE(writer != nullptr);
118 // Write attr section.
119 AddEventType("cpu-cycles");
120 attrs_[0].sample_id_all = 1;
121 attrs_[0].sample_type |= PERF_SAMPLE_TIME;
122 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_));
124 // Write data section.
125 MmapRecord r1 = CreateMmapRecord(attrs_[0], true, 1, 1, 0x100, 0x2000, 0x3000, "mmap_record1");
128 r1.sample_id.time_data.time = 2;
129 r2.sample_id.time_data.time = 1;
130 r3.sample_id.time_data.time = 3;
131 ASSERT_TRUE(writer->WriteData(r1.BinaryFormat()));
132 ASSERT_TRUE(writer->WriteData(r2.BinaryFormat()));
133 ASSERT_TRUE(writer->WriteData(r3.BinaryFormat()));
134 ASSERT_TRUE(writer->Close());
136 // Read from a record file.
137 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(filename_);
138 ASSERT_TRUE(reader != nullptr);
139 std::vector<std::unique_ptr<Record>> records = reader->DataSection();
140 ASSERT_EQ(3u, records.size());
141 CheckRecordEqual(r2, *records[0]);
142 CheckRecordEqual(r1, *records[1]);
143 CheckRecordEqual(r3, *records[2]);
145 ASSERT_TRUE(reader->Close());
148 TEST_F(RecordFileTest, record_more_than_one_attr) {
149 // Write to a record file.
150 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(filename_);
151 ASSERT_TRUE(writer != nullptr);
153 // Write attr section.
154 AddEventType("cpu-cycles");
155 AddEventType("cpu-clock");
156 AddEventType("task-clock");
157 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_));
159 ASSERT_TRUE(writer->Close());
161 // Read from a record file.
162 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(filename_);
163 ASSERT_TRUE(reader != nullptr);
164 std::vector<const FileAttr*> file_attrs = reader->AttrSection();
165 ASSERT_EQ(3u, file_attrs.size());
166 for (size_t i = 0; i < file_attrs.size(); ++i) {
167 ASSERT_EQ(0, memcmp(&file_attrs[i]->attr, attr_ids_[i].attr, sizeof(perf_event_attr)));
168 std::vector<uint64_t> ids = reader->IdsForAttr(file_attrs[i]);
169 ASSERT_EQ(ids, attr_ids_[i].ids);