1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 #include <gtest/gtest.h> 18 19 #include <string.h> 20 21 #include <memory> 22 23 #include <android-base/test_utils.h> 24 25 #include "environment.h" 26 #include "event_attr.h" 27 #include "event_type.h" 28 #include "record.h" 29 #include "record_file.h" 30 31 #include "record_equal_test.h" 32 33 using namespace PerfFileFormat; 34 35 class RecordFileTest : public ::testing::Test { 36 protected: 37 void AddEventType(const std::string& event_type_str) { 38 std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType(event_type_str); 39 ASSERT_TRUE(event_type_modifier != nullptr); 40 perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type); 41 attrs_.push_back(std::unique_ptr<perf_event_attr>(new perf_event_attr(attr))); 42 AttrWithId attr_id; 43 attr_id.attr = attrs_.back().get(); 44 attr_id.ids.push_back(attrs_.size()); // Fake id. 45 attr_ids_.push_back(attr_id); 46 } 47 48 TemporaryFile tmpfile_; 49 std::vector<std::unique_ptr<perf_event_attr>> attrs_; 50 std::vector<AttrWithId> attr_ids_; 51 }; 52 53 TEST_F(RecordFileTest, smoke) { 54 // Write to a record file. 55 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path); 56 ASSERT_TRUE(writer != nullptr); 57 58 // Write attr section. 59 AddEventType("cpu-cycles"); 60 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_)); 61 62 // Write data section. 63 MmapRecord mmap_record = CreateMmapRecord(*(attr_ids_[0].attr), true, 1, 1, 0x1000, 0x2000, 64 0x3000, "mmap_record_example"); 65 ASSERT_TRUE(writer->WriteData(mmap_record.BinaryFormat())); 66 67 // Write feature section. 68 ASSERT_TRUE(writer->WriteFeatureHeader(1)); 69 char p[BuildId::Size()]; 70 for (size_t i = 0; i < BuildId::Size(); ++i) { 71 p[i] = i; 72 } 73 BuildId build_id(p); 74 BuildIdRecord build_id_record = CreateBuildIdRecord(false, getpid(), build_id, "init"); 75 ASSERT_TRUE(writer->WriteBuildIdFeature({build_id_record})); 76 ASSERT_TRUE(writer->Close()); 77 78 // Read from a record file. 79 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile_.path); 80 ASSERT_TRUE(reader != nullptr); 81 const std::vector<FileAttr>& file_attrs = reader->AttrSection(); 82 ASSERT_EQ(1u, file_attrs.size()); 83 ASSERT_EQ(0, memcmp(&file_attrs[0].attr, attr_ids_[0].attr, sizeof(perf_event_attr))); 84 std::vector<uint64_t> ids; 85 ASSERT_TRUE(reader->ReadIdsForAttr(file_attrs[0], &ids)); 86 ASSERT_EQ(ids, attr_ids_[0].ids); 87 88 // Read and check data section. 89 std::vector<std::unique_ptr<Record>> records = reader->DataSection(); 90 ASSERT_EQ(1u, records.size()); 91 CheckRecordEqual(mmap_record, *records[0]); 92 93 // Read and check feature section. 94 std::vector<BuildIdRecord> build_id_records = reader->ReadBuildIdFeature(); 95 ASSERT_EQ(1u, build_id_records.size()); 96 CheckRecordEqual(build_id_record, build_id_records[0]); 97 98 ASSERT_TRUE(reader->Close()); 99 } 100 101 TEST_F(RecordFileTest, records_sorted_by_time) { 102 // Write to a record file. 103 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path); 104 ASSERT_TRUE(writer != nullptr); 105 106 // Write attr section. 107 AddEventType("cpu-cycles"); 108 attrs_[0]->sample_id_all = 1; 109 attrs_[0]->sample_type |= PERF_SAMPLE_TIME; 110 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_)); 111 112 // Write data section. 113 MmapRecord r1 = 114 CreateMmapRecord(*(attr_ids_[0].attr), true, 1, 1, 0x100, 0x2000, 0x3000, "mmap_record1"); 115 MmapRecord r2 = r1; 116 MmapRecord r3 = r1; 117 r1.sample_id.time_data.time = 2; 118 r2.sample_id.time_data.time = 1; 119 r3.sample_id.time_data.time = 3; 120 ASSERT_TRUE(writer->WriteData(r1.BinaryFormat())); 121 ASSERT_TRUE(writer->WriteData(r2.BinaryFormat())); 122 ASSERT_TRUE(writer->WriteData(r3.BinaryFormat())); 123 ASSERT_TRUE(writer->Close()); 124 125 // Read from a record file. 126 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile_.path); 127 ASSERT_TRUE(reader != nullptr); 128 std::vector<std::unique_ptr<Record>> records = reader->DataSection(); 129 ASSERT_EQ(3u, records.size()); 130 CheckRecordEqual(r2, *records[0]); 131 CheckRecordEqual(r1, *records[1]); 132 CheckRecordEqual(r3, *records[2]); 133 134 ASSERT_TRUE(reader->Close()); 135 } 136 137 TEST_F(RecordFileTest, record_more_than_one_attr) { 138 // Write to a record file. 139 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path); 140 ASSERT_TRUE(writer != nullptr); 141 142 // Write attr section. 143 AddEventType("cpu-cycles"); 144 AddEventType("cpu-clock"); 145 AddEventType("task-clock"); 146 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_)); 147 148 ASSERT_TRUE(writer->Close()); 149 150 // Read from a record file. 151 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile_.path); 152 ASSERT_TRUE(reader != nullptr); 153 const std::vector<FileAttr>& file_attrs = reader->AttrSection(); 154 ASSERT_EQ(3u, file_attrs.size()); 155 for (size_t i = 0; i < file_attrs.size(); ++i) { 156 ASSERT_EQ(0, memcmp(&file_attrs[i].attr, attr_ids_[i].attr, sizeof(perf_event_attr))); 157 std::vector<uint64_t> ids; 158 ASSERT_TRUE(reader->ReadIdsForAttr(file_attrs[i], &ids)); 159 ASSERT_EQ(ids, attr_ids_[i].ids); 160 } 161 } 162