blob: f51778517469c7d8b545b6b741e3a9540bc4c61a [file] [log] [blame]
Hector Dearman0d300332017-11-22 11:05:34 +00001/*
2 * Copyright (C) 2017 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 "cpu_reader.h"
18
19#include "ftrace_procfs.h"
20#include "gtest/gtest.h"
21#include "proto_translation_table.h"
22
Hector Dearmanbefe55b2017-11-24 19:02:59 +000023#include "protozero/scattered_stream_writer.h"
24#include "scattered_stream_delegate_for_testing.h"
25
Primiano Tucci5f48d7b2017-11-27 16:57:13 +000026#include "protos/ftrace/ftrace_event.pb.h"
27#include "protos/ftrace/ftrace_event_bundle.pb.h"
28#include "protos/ftrace/ftrace_event_bundle.pbzero.h"
29
Hector Dearman0d300332017-11-22 11:05:34 +000030namespace perfetto {
31
Hector Dearmanbefe55b2017-11-24 19:02:59 +000032namespace {
33
34const size_t kPageSize = 4096;
35
36std::unique_ptr<uint8_t[]> MakeBuffer(size_t size) {
37 return std::unique_ptr<uint8_t[]>(new uint8_t[size]);
38}
39
40class BinaryWriter {
41 public:
42 BinaryWriter(uint8_t* ptr, size_t size) : ptr_(ptr), size_(size) {}
43
44 template <typename T>
45 void Write(T t) {
46 memcpy(ptr_, &t, sizeof(T));
47 ptr_ += sizeof(T);
48 PERFETTO_CHECK(ptr_ < ptr_ + size_);
49 }
50
51 void WriteEventHeader(uint32_t time_delta, uint32_t entry_type) {
52 // Entry header is a packed time delta (d) and type (t):
53 // dddddddd dddddddd dddddddd dddttttt
Hector Dearman8d8ccd32017-11-27 16:06:34 +000054 Write<uint32_t>((time_delta << 5) | (entry_type & 0x1f));
Hector Dearmanbefe55b2017-11-24 19:02:59 +000055 }
56
57 void WriteString(const char* s) {
58 char c;
59 while ((c = *s++)) {
60 Write<char>(c);
61 }
62 }
63
64 private:
65 uint8_t* ptr_;
66 size_t size_;
67};
68
69} // namespace
70
Hector Dearman0d300332017-11-22 11:05:34 +000071TEST(EventFilterTest, EventFilter) {
72 using Event = ProtoTranslationTable::Event;
73 using Field = ProtoTranslationTable::Field;
74
75 std::vector<Field> common_fields;
76 std::vector<Event> events;
77
78 {
79 Event event;
80 event.name = "foo";
81 event.ftrace_event_id = 1;
82 events.push_back(event);
83 }
84
85 {
86 Event event;
87 event.name = "bar";
88 event.ftrace_event_id = 10;
89 events.push_back(event);
90 }
91
92 ProtoTranslationTable table(events, std::move(common_fields));
93 EventFilter filter(table, std::set<std::string>({"foo"}));
94
95 EXPECT_TRUE(filter.IsEventEnabled(1));
96 EXPECT_FALSE(filter.IsEventEnabled(2));
97 EXPECT_FALSE(filter.IsEventEnabled(10));
98}
99
100TEST(CpuReaderTest, ReadAndAdvanceNumber) {
101 uint64_t expected = 42;
102 uint64_t actual = 0;
103 uint8_t buffer[8] = {};
104 const uint8_t* start = buffer;
105 const uint8_t* ptr = buffer;
106 memcpy(&buffer, &expected, 8);
107 EXPECT_TRUE(CpuReader::ReadAndAdvance<uint64_t>(&ptr, ptr + 8, &actual));
108 EXPECT_EQ(ptr, start + 8);
109 EXPECT_EQ(actual, expected);
110}
111
112TEST(CpuReaderTest, ReadAndAdvancePlainStruct) {
113 struct PlainStruct {
114 uint64_t timestamp;
115 uint64_t length;
116 };
117
118 uint64_t expected[2] = {42, 999};
119 PlainStruct actual;
120 uint8_t buffer[16] = {};
121 const uint8_t* start = buffer;
122 const uint8_t* ptr = buffer;
123 memcpy(&buffer, &expected, 16);
124 EXPECT_TRUE(CpuReader::ReadAndAdvance<PlainStruct>(&ptr, ptr + 16, &actual));
125 EXPECT_EQ(ptr, start + 16);
Oystein Eftevaagdd727e42017-12-05 08:49:55 -0800126 EXPECT_EQ(actual.timestamp, 42ul);
127 EXPECT_EQ(actual.length, 999ul);
Hector Dearman0d300332017-11-22 11:05:34 +0000128}
129
130TEST(CpuReaderTest, ReadAndAdvanceComplexStruct) {
131 struct ComplexStruct {
132 uint64_t timestamp;
133 uint32_t length;
134 uint32_t : 24;
135 uint32_t overwrite : 8;
136 };
137
138 uint64_t expected[2] = {42, 0xcdffffffabababab};
139 ComplexStruct actual = {};
140 uint8_t buffer[16] = {};
141 const uint8_t* start = buffer;
142 const uint8_t* ptr = buffer;
143 memcpy(&buffer, &expected, 16);
144 EXPECT_TRUE(
145 CpuReader::ReadAndAdvance<ComplexStruct>(&ptr, ptr + 16, &actual));
146 EXPECT_EQ(ptr, start + 16);
Oystein Eftevaagdd727e42017-12-05 08:49:55 -0800147 EXPECT_EQ(actual.timestamp, 42ul);
Hector Dearman0d300332017-11-22 11:05:34 +0000148 EXPECT_EQ(actual.length, 0xabababab);
Oystein Eftevaagdd727e42017-12-05 08:49:55 -0800149 EXPECT_EQ(actual.overwrite, 0xCDu);
Hector Dearman0d300332017-11-22 11:05:34 +0000150}
151
152TEST(CpuReaderTest, ReadAndAdvanceOverruns) {
153 uint64_t result = 42;
154 uint8_t buffer[7] = {};
155 const uint8_t* start = buffer;
156 const uint8_t* ptr = buffer;
157 EXPECT_FALSE(CpuReader::ReadAndAdvance<uint64_t>(&ptr, ptr + 7, &result));
158 EXPECT_EQ(ptr, start);
Oystein Eftevaagdd727e42017-12-05 08:49:55 -0800159 EXPECT_EQ(result, 42ul);
Hector Dearman0d300332017-11-22 11:05:34 +0000160}
161
162TEST(CpuReaderTest, ReadAndAdvanceAtEnd) {
163 uint8_t result = 42;
164 uint8_t buffer[8] = {};
165 const uint8_t* start = buffer;
166 const uint8_t* ptr = buffer;
167 EXPECT_FALSE(CpuReader::ReadAndAdvance<uint8_t>(&ptr, ptr, &result));
168 EXPECT_EQ(ptr, start);
169 EXPECT_EQ(result, 42);
170}
171
172TEST(CpuReaderTest, ReadAndAdvanceUnderruns) {
173 uint64_t expected = 42;
174 uint64_t actual = 0;
175 uint8_t buffer[9] = {};
176 const uint8_t* start = buffer;
177 const uint8_t* ptr = buffer;
178 memcpy(&buffer, &expected, 8);
179 EXPECT_TRUE(CpuReader::ReadAndAdvance<uint64_t>(&ptr, ptr + 8, &actual));
180 EXPECT_EQ(ptr, start + 8);
181 EXPECT_EQ(actual, expected);
182}
183
184TEST(CpuReaderTest, ParseEmpty) {
185 std::string path = "ftrace_reader/test/data/android_seed_N2F62_3.10.49/";
186 FtraceProcfs ftrace_procfs(path);
Hector Dearman8d8ccd32017-11-27 16:06:34 +0000187 auto table = ProtoTranslationTable::Create(&ftrace_procfs);
Hector Dearman0d300332017-11-22 11:05:34 +0000188 CpuReader(table.get(), 42, base::ScopedFile());
189}
190
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000191TEST(CpuReaderTest, ParseSimpleEvent) {
192 std::string path = "ftrace_reader/test/data/android_seed_N2F62_3.10.49/";
193 FtraceProcfs ftrace(path);
Hector Dearman8d8ccd32017-11-27 16:06:34 +0000194 auto table = ProtoTranslationTable::Create(&ftrace);
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000195
196 std::unique_ptr<uint8_t[]> in_page = MakeBuffer(kPageSize);
197 std::unique_ptr<uint8_t[]> out_page = MakeBuffer(kPageSize);
198
199 BinaryWriter writer(in_page.get(), kPageSize);
200 // Timestamp:
201 writer.Write<uint64_t>(999);
202 // Page length:
203 writer.Write<uint64_t>(35);
204 // 4 Header:
205 writer.WriteEventHeader(1 /* time delta */, 8 /* entry type */);
206 // 6 Event type:
207 writer.Write<uint16_t>(5);
208 // 7 Flags:
209 writer.Write<uint8_t>(0);
210 // 8 Preempt count:
211 writer.Write<uint8_t>(0);
212 // 12 PID:
213 writer.Write<uint32_t>(72);
214 // 20 Instruction pointer:
215 writer.Write<uint64_t>(0);
216 // 35 String:
217 writer.WriteString("Hello, world!\n");
218
219 EventFilter filter(*table, std::set<std::string>({"print"}));
220
221 perfetto::ScatteredStreamDelegateForTesting delegate(kPageSize);
222 protozero::ScatteredStreamWriter stream_writer(&delegate);
Hector Dearman8d8ccd32017-11-27 16:06:34 +0000223 delegate.set_writer(&stream_writer);
Primiano Tucci5f48d7b2017-11-27 16:57:13 +0000224 protos::pbzero::FtraceEventBundle message;
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000225 message.Reset(&stream_writer);
226
227 CpuReader::ParsePage(42 /* cpu number */, in_page.get(), kPageSize, &filter,
Hector Dearman8d8ccd32017-11-27 16:06:34 +0000228 &message, table.get());
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000229
230 size_t msg_size =
231 delegate.chunks().size() * kPageSize - stream_writer.bytes_available();
Hector Dearman8d8ccd32017-11-27 16:06:34 +0000232 std::unique_ptr<uint8_t[]> proto = delegate.StitchChunks(msg_size);
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000233
Primiano Tucci5f48d7b2017-11-27 16:57:13 +0000234 protos::FtraceEventBundle proto_bundle;
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000235 proto_bundle.ParseFromArray(proto.get(), static_cast<int>(msg_size));
236
Oystein Eftevaagdd727e42017-12-05 08:49:55 -0800237 EXPECT_EQ(proto_bundle.cpu(), 42u);
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000238 ASSERT_EQ(proto_bundle.event().size(), 1);
Primiano Tucci5f48d7b2017-11-27 16:57:13 +0000239 const protos::FtraceEvent& proto_event = proto_bundle.event().Get(0);
Oystein Eftevaagdd727e42017-12-05 08:49:55 -0800240 EXPECT_EQ(proto_event.pid(), 72u);
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000241 EXPECT_TRUE(proto_event.has_print());
Hector Dearman8d8ccd32017-11-27 16:06:34 +0000242 // TODO(hjd): Check if this is the correct format.
243 EXPECT_EQ(proto_event.print().buf(), "Hello, world!\n");
Hector Dearmanbefe55b2017-11-24 19:02:59 +0000244}
245
Hector Dearman0d300332017-11-22 11:05:34 +0000246} // namespace perfetto