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
24class RecordTest : public ::testing::Test {
25 protected:
26  virtual void SetUp() {
27    const EventType* type = FindEventTypeByName("cpu-cycles");
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
43TEST_F(RecordTest, MmapRecordMatchBinary) {
44  MmapRecord record(event_attr, true, 1, 2, 0x1000, 0x2000, 0x3000,
45                    "MmapRecord", 0);
46  CheckRecordMatchBinary(record);
47}
48
49TEST_F(RecordTest, CommRecordMatchBinary) {
50  CommRecord record(event_attr, 1, 2, "CommRecord", 0, 7);
51  CheckRecordMatchBinary(record);
52}
53
54TEST_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});
59  CheckRecordMatchBinary(record);
60}
61
62TEST_F(RecordTest, RecordCache_smoke) {
63  event_attr.sample_id_all = 1;
64  event_attr.sample_type |= PERF_SAMPLE_TIME;
65  RecordCache cache(true, 2, 2);
66
67  // Push r1.
68  MmapRecord* r1 = new MmapRecord(event_attr, true, 1, 1, 0x100, 0x200, 0x300,
69                                  "mmap_record1", 0, 3);
70  cache.Push(std::unique_ptr<Record>(r1));
71  ASSERT_EQ(nullptr, cache.Pop());
72
73  // Push r2.
74  MmapRecord* r2 = new MmapRecord(event_attr, true, 1, 1, 0x100, 0x200, 0x300,
75                                  "mmap_record1", 0, 1);
76  cache.Push(std::unique_ptr<Record>(r2));
77  // Pop r2.
78  std::unique_ptr<Record> popped_r = cache.Pop();
79  ASSERT_TRUE(popped_r != nullptr);
80  ASSERT_EQ(r2, popped_r.get());
81  ASSERT_EQ(nullptr, cache.Pop());
82
83  // Push r3.
84  MmapRecord* r3 = new MmapRecord(event_attr, true, 1, 1, 0x100, 0x200, 0x300,
85                                  "mmap_record1", 0, 4);
86  cache.Push(std::unique_ptr<Record>(r3));
87  ASSERT_EQ(nullptr, cache.Pop());
88
89  // Push r4.
90  MmapRecord* r4 = new MmapRecord(event_attr, true, 1, 1, 0x100, 0x200, 0x300,
91                                  "mmap_record1", 0, 6);
92  cache.Push(std::unique_ptr<Record>(r4));
93  // Pop r1.
94  popped_r = cache.Pop();
95  ASSERT_TRUE(popped_r != nullptr);
96  ASSERT_EQ(r1, popped_r.get());
97  // Pop r3.
98  popped_r = cache.Pop();
99  ASSERT_TRUE(popped_r != nullptr);
100  ASSERT_EQ(r3, popped_r.get());
101  ASSERT_EQ(nullptr, cache.Pop());
102  // Pop r4.
103  std::vector<std::unique_ptr<Record>> last_records = cache.PopAll();
104  ASSERT_EQ(1u, last_records.size());
105  ASSERT_EQ(r4, last_records[0].get());
106}
107
108TEST_F(RecordTest, RecordCache_FIFO) {
109  event_attr.sample_id_all = 1;
110  event_attr.sample_type |= PERF_SAMPLE_TIME;
111  RecordCache cache(true, 2, 2);
112  std::vector<MmapRecord*> records;
113  for (size_t i = 0; i < 10; ++i) {
114    records.push_back(new MmapRecord(event_attr, true, 1, i, 0x100, 0x200,
115                                     0x300, "mmap_record1", 0));
116    cache.Push(std::unique_ptr<Record>(records.back()));
117  }
118  std::vector<std::unique_ptr<Record>> out_records = cache.PopAll();
119  ASSERT_EQ(records.size(), out_records.size());
120  for (size_t i = 0; i < records.size(); ++i) {
121    ASSERT_EQ(records[i], out_records[i].get());
122  }
123}
124
125TEST_F(RecordTest, RecordCache_PushRecordVector) {
126  event_attr.sample_id_all = 1;
127  event_attr.sample_type |= PERF_SAMPLE_TIME;
128  RecordCache cache(true, 2, 2);
129  MmapRecord* r1 = new MmapRecord(event_attr, true, 1, 1, 0x100, 0x200, 0x300,
130                                  "mmap_record1", 0, 1);
131  MmapRecord* r2 = new MmapRecord(event_attr, true, 1, 1, 0x100, 0x200, 0x300,
132                                  "mmap_record1", 0, 3);
133  std::vector<std::unique_ptr<Record>> records;
134  records.push_back(std::unique_ptr<Record>(r1));
135  records.push_back(std::unique_ptr<Record>(r2));
136  cache.Push(std::move(records));
137  std::unique_ptr<Record> popped_r = cache.Pop();
138  ASSERT_TRUE(popped_r != nullptr);
139  ASSERT_EQ(r1, popped_r.get());
140  std::vector<std::unique_ptr<Record>> last_records = cache.PopAll();
141  ASSERT_EQ(1u, last_records.size());
142  ASSERT_EQ(r2, last_records[0].get());
143}
144
145TEST_F(RecordTest, SampleRecord_exclude_kernel_callchain) {
146  SampleRecord r(event_attr, 0, 1, 0, 0, 0, 0, 0, {});
147  ASSERT_EQ(0u, r.ExcludeKernelCallChain());
148
149  event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
150  SampleRecord r1(event_attr, 0, 1, 0, 0, 0, 0, 0, {PERF_CONTEXT_USER, 2});
151  ASSERT_EQ(1u, r1.ExcludeKernelCallChain());
152  ASSERT_EQ(2u, r1.ip_data.ip);
153  SampleRecord r2(event_attr, r1.BinaryForTestingOnly());
154  ASSERT_EQ(1u, r.ip_data.ip);
155  ASSERT_EQ(2u, r2.callchain_data.ip_nr);
156  ASSERT_EQ(PERF_CONTEXT_USER, r2.callchain_data.ips[0]);
157  ASSERT_EQ(2u, r2.callchain_data.ips[1]);
158
159  SampleRecord r3(event_attr, 0, 1, 0, 0, 0, 0, 0, {1, PERF_CONTEXT_USER, 2});
160  ASSERT_EQ(1u, r3.ExcludeKernelCallChain());
161  ASSERT_EQ(2u, r3.ip_data.ip);
162  SampleRecord r4(event_attr, r3.BinaryForTestingOnly());
163  ASSERT_EQ(2u, r4.ip_data.ip);
164  ASSERT_EQ(3u, r4.callchain_data.ip_nr);
165  ASSERT_EQ(PERF_CONTEXT_USER, r4.callchain_data.ips[0]);
166  ASSERT_EQ(PERF_CONTEXT_USER, r4.callchain_data.ips[1]);
167  ASSERT_EQ(2u, r4.callchain_data.ips[2]);
168
169  SampleRecord r5(event_attr, 0, 1, 0, 0, 0, 0, 0, {1, 2});
170  ASSERT_EQ(0u, r5.ExcludeKernelCallChain());
171  SampleRecord r6(event_attr, 0, 1, 0, 0, 0, 0, 0, {1, 2, PERF_CONTEXT_USER});
172  ASSERT_EQ(0u, r6.ExcludeKernelCallChain());
173}
174