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 "event_attr.h" 20 #include "event_type.h" 21 #include "record.h" 22 #include "record_equal_test.h" 23 24 class RecordTest : public ::testing::Test { 25 protected: 26 virtual void SetUp() { 27 const EventType* type = FindEventTypeByName("cpu-clock"); 28 ASSERT_TRUE(type != nullptr); 29 event_attr = CreateDefaultPerfEventAttr(*type); 30 event_attr.sample_id_all = 1; 31 } 32 33 void CheckRecordMatchBinary(Record& record) { 34 std::vector<std::unique_ptr<Record>> records = 35 ReadRecordsFromBuffer(event_attr, record.BinaryForTestingOnly(), record.size()); 36 ASSERT_EQ(1u, records.size()); 37 CheckRecordEqual(record, *records[0]); 38 } 39 40 perf_event_attr event_attr; 41 }; 42 43 TEST_F(RecordTest, MmapRecordMatchBinary) { 44 MmapRecord record(event_attr, true, 1, 2, 0x1000, 0x2000, 0x3000, 45 "MmapRecord", 0); 46 CheckRecordMatchBinary(record); 47 } 48 49 TEST_F(RecordTest, CommRecordMatchBinary) { 50 CommRecord record(event_attr, 1, 2, "CommRecord", 0, 7); 51 CheckRecordMatchBinary(record); 52 } 53 54 TEST_F(RecordTest, SampleRecordMatchBinary) { 55 event_attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME 56 | PERF_SAMPLE_ID | PERF_SAMPLE_CPU 57 | PERF_SAMPLE_PERIOD | PERF_SAMPLE_CALLCHAIN; 58 SampleRecord record(event_attr, 1, 2, 3, 4, 5, 6, 7, {8, 9, 10}, {}, 0); 59 CheckRecordMatchBinary(record); 60 } 61 62 TEST_F(RecordTest, SampleRecord_exclude_kernel_callchain) { 63 SampleRecord r(event_attr, 0, 1, 0, 0, 0, 0, 0, {}, {}, 0); 64 ASSERT_TRUE(r.ExcludeKernelCallChain()); 65 66 event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN; 67 SampleRecord r1(event_attr, 0, 1, 0, 0, 0, 0, 0, {PERF_CONTEXT_USER, 2}, {}, 0); 68 ASSERT_TRUE(r1.ExcludeKernelCallChain()); 69 ASSERT_EQ(2u, r1.ip_data.ip); 70 SampleRecord r2(event_attr, r1.BinaryForTestingOnly()); 71 ASSERT_EQ(1u, r.ip_data.ip); 72 ASSERT_EQ(2u, r2.callchain_data.ip_nr); 73 ASSERT_EQ(PERF_CONTEXT_USER, r2.callchain_data.ips[0]); 74 ASSERT_EQ(2u, r2.callchain_data.ips[1]); 75 76 SampleRecord r3(event_attr, 0, 1, 0, 0, 0, 0, 0, {1, PERF_CONTEXT_USER, 2}, {}, 0); 77 ASSERT_TRUE(r3.ExcludeKernelCallChain()); 78 ASSERT_EQ(2u, r3.ip_data.ip); 79 SampleRecord r4(event_attr, r3.BinaryForTestingOnly()); 80 ASSERT_EQ(2u, r4.ip_data.ip); 81 ASSERT_EQ(3u, r4.callchain_data.ip_nr); 82 ASSERT_EQ(PERF_CONTEXT_USER, r4.callchain_data.ips[0]); 83 ASSERT_EQ(PERF_CONTEXT_USER, r4.callchain_data.ips[1]); 84 ASSERT_EQ(2u, r4.callchain_data.ips[2]); 85 86 SampleRecord r5(event_attr, 0, 1, 0, 0, 0, 0, 0, {1, 2}, {}, 0); 87 ASSERT_FALSE(r5.ExcludeKernelCallChain()); 88 SampleRecord r6(event_attr, 0, 1, 0, 0, 0, 0, 0, {1, 2, PERF_CONTEXT_USER}, {}, 0); 89 ASSERT_FALSE(r6.ExcludeKernelCallChain()); 90 91 // Process consecutive context values. 92 SampleRecord r7(event_attr, 0, 1, 0, 0, 0, 0, 0, 93 {1, 2, PERF_CONTEXT_USER, PERF_CONTEXT_USER, 3, 4}, {}, 0); 94 r7.header.misc = PERF_RECORD_MISC_KERNEL; 95 ASSERT_TRUE(r7.ExcludeKernelCallChain()); 96 CheckRecordEqual(r7, SampleRecord(event_attr, 0, 3, 0, 0, 0, 0, 0, 97 {PERF_CONTEXT_USER, PERF_CONTEXT_USER, PERF_CONTEXT_USER, 98 PERF_CONTEXT_USER, 3, 4}, {}, 0)); 99 } 100 101 TEST_F(RecordTest, SampleRecord_ReplaceRegAndStackWithCallChain) { 102 event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER; 103 SampleRecord expected(event_attr, 0, 1, 2, 3, 4, 5, 6, {1, PERF_CONTEXT_USER, 2, 3, 4, 5}, {}, 104 0); 105 for (size_t stack_size : {8, 1024}) { 106 SampleRecord r(event_attr, 0, 1, 2, 3, 4, 5, 6, {1}, std::vector<char>(stack_size), 10); 107 r.ReplaceRegAndStackWithCallChain({2, 3, 4, 5}); 108 CheckRecordMatchBinary(r); 109 CheckRecordEqual(r, expected); 110 } 111 } 112 113 TEST_F(RecordTest, SampleRecord_UpdateUserCallChain) { 114 event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER; 115 SampleRecord r(event_attr, 0, 1, 2, 3, 4, 5, 6, {1, PERF_CONTEXT_USER, 2}, {}, 0); 116 r.UpdateUserCallChain({3, 4, 5}); 117 CheckRecordMatchBinary(r); 118 SampleRecord expected(event_attr, 0, 1, 2, 3, 4, 5, 6, {1, PERF_CONTEXT_USER, 3, 4, 5}, {}, 0); 119 CheckRecordEqual(r, expected); 120 } 121 122 TEST_F(RecordTest, SampleRecord_AdjustCallChainGeneratedByKernel) { 123 event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER; 124 SampleRecord r(event_attr, 0, 1, 2, 3, 4, 5, 6, {1, 5, 0, PERF_CONTEXT_USER, 6, 0}, {}, 0); 125 r.header.misc = PERF_RECORD_MISC_KERNEL; 126 r.AdjustCallChainGeneratedByKernel(); 127 uint64_t adjustValue = (GetBuildArch() == ARCH_ARM || GetBuildArch() == ARCH_ARM64) ? 2 : 1; 128 SampleRecord expected(event_attr, 0, 1, 2, 3, 4, 5, 6, 129 {1, 5 - adjustValue, PERF_CONTEXT_KERNEL, PERF_CONTEXT_USER, 130 6 - adjustValue, PERF_CONTEXT_USER}, {}, 0); 131 expected.header.misc = PERF_RECORD_MISC_KERNEL; 132 CheckRecordEqual(r, expected); 133 } 134 135 TEST_F(RecordTest, CommRecord) { 136 CommRecord r(event_attr, 1, 2, "init_name", 3, 4); 137 size_t record_size = r.size(); 138 std::string new_name = "a_much_longer_name"; 139 r.SetCommandName(new_name); 140 ASSERT_EQ(r.size(), record_size + 8); 141 ASSERT_EQ(std::string(r.comm), new_name); 142 ASSERT_EQ(r.data->pid, 1u); 143 ASSERT_EQ(r.data->tid, 2u); 144 ASSERT_EQ(r.sample_id.id_data.id, 3u); 145 ASSERT_EQ(r.sample_id.time_data.time, 4u); 146 CheckRecordMatchBinary(r); 147 } 148