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 attr.sample_id_all = 1; 42 attrs_.push_back(std::unique_ptr<perf_event_attr>(new perf_event_attr(attr))); 43 EventAttrWithId attr_id; 44 attr_id.attr = attrs_.back().get(); 45 attr_id.ids.push_back(attrs_.size()); // Fake id. 46 attr_ids_.push_back(attr_id); 47 } 48 49 TemporaryFile tmpfile_; 50 std::vector<std::unique_ptr<perf_event_attr>> attrs_; 51 std::vector<EventAttrWithId> attr_ids_; 52 }; 53 54 TEST_F(RecordFileTest, smoke) { 55 // Write to a record file. 56 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path); 57 ASSERT_TRUE(writer != nullptr); 58 59 // Write attr section. 60 AddEventType("cpu-cycles"); 61 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_)); 62 63 // Write data section. 64 MmapRecord mmap_record(*(attr_ids_[0].attr), true, 1, 1, 0x1000, 0x2000, 65 0x3000, "mmap_record_example", attr_ids_[0].ids[0]); 66 ASSERT_TRUE(writer->WriteRecord(mmap_record)); 67 68 // Write feature section. 69 ASSERT_TRUE(writer->BeginWriteFeatures(1)); 70 char p[BuildId::Size()]; 71 for (size_t i = 0; i < BuildId::Size(); ++i) { 72 p[i] = i; 73 } 74 BuildId build_id(p); 75 std::vector<BuildIdRecord> build_id_records; 76 build_id_records.push_back(BuildIdRecord(false, getpid(), build_id, "init")); 77 ASSERT_TRUE(writer->WriteBuildIdFeature(build_id_records)); 78 ASSERT_TRUE(writer->EndWriteFeatures()); 79 ASSERT_TRUE(writer->Close()); 80 81 // Read from a record file. 82 std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile_.path); 83 ASSERT_TRUE(reader != nullptr); 84 std::vector<EventAttrWithId> attrs = reader->AttrSection(); 85 ASSERT_EQ(1u, attrs.size()); 86 ASSERT_EQ(0, memcmp(attrs[0].attr, attr_ids_[0].attr, sizeof(perf_event_attr))); 87 ASSERT_EQ(attrs[0].ids, attr_ids_[0].ids); 88 89 // Read and check data section. 90 std::vector<std::unique_ptr<Record>> records = reader->DataSection(); 91 ASSERT_EQ(1u, records.size()); 92 CheckRecordEqual(mmap_record, *records[0]); 93 94 // Read and check feature section. 95 std::vector<BuildIdRecord> read_build_id_records = reader->ReadBuildIdFeature(); 96 ASSERT_EQ(1u, read_build_id_records.size()); 97 CheckRecordEqual(read_build_id_records[0], build_id_records[0]); 98 99 ASSERT_TRUE(reader->Close()); 100 } 101 102 TEST_F(RecordFileTest, records_sorted_by_time) { 103 // Write to a record file. 104 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path); 105 ASSERT_TRUE(writer != nullptr); 106 107 // Write attr section. 108 AddEventType("cpu-cycles"); 109 attrs_[0]->sample_id_all = 1; 110 attrs_[0]->sample_type |= PERF_SAMPLE_TIME; 111 ASSERT_TRUE(writer->WriteAttrSection(attr_ids_)); 112 113 // Write data section. 114 MmapRecord r1(*(attr_ids_[0].attr), true, 1, 1, 0x100, 0x2000, 0x3000, "mmap_record1", 115 attr_ids_[0].ids[0], 2); 116 MmapRecord r2(*(attr_ids_[0].attr), true, 1, 1, 0x100, 0x2000, 0x3000, "mmap_record1", 117 attr_ids_[0].ids[0], 1); 118 MmapRecord r3(*(attr_ids_[0].attr), true, 1, 1, 0x100, 0x2000, 0x3000, "mmap_record1", 119 attr_ids_[0].ids[0], 3); 120 ASSERT_TRUE(writer->WriteRecord(r1)); 121 ASSERT_TRUE(writer->WriteRecord(r2)); 122 ASSERT_TRUE(writer->WriteRecord(r3)); 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 std::vector<EventAttrWithId> attrs = reader->AttrSection(); 154 ASSERT_EQ(3u, attrs.size()); 155 for (size_t i = 0; i < attrs.size(); ++i) { 156 ASSERT_EQ(0, memcmp(attrs[i].attr, attr_ids_[i].attr, sizeof(perf_event_attr))); 157 ASSERT_EQ(attrs[i].ids, attr_ids_[i].ids); 158 } 159 } 160