1 /*
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 "src/traced/probes/ftrace/proto_translation_table.h"
18
19 #include "src/base/test/gtest_test_suite.h"
20 #include "src/base/test/utils.h"
21 #include "src/traced/probes/ftrace/compact_sched.h"
22 #include "src/traced/probes/ftrace/event_info.h"
23 #include "src/traced/probes/ftrace/ftrace_procfs.h"
24 #include "test/gtest_and_gmock.h"
25
26 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
27 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
28
29 using testing::_;
30 using testing::Values;
31 using testing::ValuesIn;
32 using testing::TestWithParam;
33 using testing::Return;
34 using testing::AnyNumber;
35 using testing::IsNull;
36 using testing::Contains;
37 using testing::Eq;
38 using testing::Pointee;
39
40 namespace perfetto {
41 namespace {
42 using protozero::proto_utils::ProtoSchemaType;
43
44 class MockFtraceProcfs : public FtraceProcfs {
45 public:
MockFtraceProcfs()46 MockFtraceProcfs() : FtraceProcfs("/root/") {}
47
48 MOCK_CONST_METHOD0(ReadPageHeaderFormat, std::string());
49 MOCK_CONST_METHOD2(ReadEventFormat,
50 std::string(const std::string& group,
51 const std::string& name));
52 };
53
54 class AllTranslationTableTest : public TestWithParam<const char*> {
55 public:
SetUp()56 void SetUp() override {
57 std::string path = base::GetTestDataPath(
58 "src/traced/probes/ftrace/test/data/" + std::string(GetParam()) + "/");
59 FtraceProcfs ftrace_procfs(path);
60 table_ = ProtoTranslationTable::Create(&ftrace_procfs, GetStaticEventInfo(),
61 GetStaticCommonFieldsInfo());
62 PERFETTO_CHECK(table_);
63 }
64
65 std::unique_ptr<ProtoTranslationTable> table_;
66 };
67
68 class TranslationTableCreationTest : public TestWithParam<uint16_t> {};
69
70 const char* kDevices[] = {
71 "android_seed_N2F62_3.10.49", "android_hammerhead_MRA59G_3.4.0",
72 };
73
TEST_P(AllTranslationTableTest,Create)74 TEST_P(AllTranslationTableTest, Create) {
75 EXPECT_TRUE(table_);
76 EXPECT_TRUE(table_->GetEvent(GroupAndName("ftrace", "print")));
77 EXPECT_TRUE(table_->GetEvent(GroupAndName("sched", "sched_switch")));
78 EXPECT_TRUE(table_->GetEvent(GroupAndName("sched", "sched_wakeup")));
79 EXPECT_TRUE(table_->GetEvent(GroupAndName("ext4", "ext4_da_write_begin")));
80 for (const Event& event : table_->events()) {
81 if (!event.ftrace_event_id)
82 continue;
83 EXPECT_TRUE(event.name);
84 EXPECT_TRUE(event.group);
85 EXPECT_TRUE(event.proto_field_id);
86 for (const Field& field : event.fields) {
87 EXPECT_TRUE(field.proto_field_id);
88 EXPECT_TRUE(field.ftrace_type);
89 EXPECT_TRUE(static_cast<int>(field.proto_field_type));
90 }
91 }
92 ASSERT_EQ(table_->common_fields().size(), 1u);
93 const Field& pid_field = table_->common_fields().at(0);
94 EXPECT_EQ(std::string(pid_field.ftrace_name), "common_pid");
95 EXPECT_EQ(pid_field.proto_field_id, 2u);
96
97 {
98 auto event = table_->GetEvent(GroupAndName("ftrace", "print"));
99 EXPECT_TRUE(event);
100 EXPECT_EQ(std::string(event->name), "print");
101 EXPECT_EQ(std::string(event->group), "ftrace");
102
103 EXPECT_EQ(event->fields.at(0).proto_field_type, ProtoSchemaType::kString);
104 EXPECT_EQ(event->fields.at(0).ftrace_type, kFtraceCString);
105 EXPECT_EQ(event->fields.at(0).strategy, kCStringToString);
106 }
107 }
108
109 INSTANTIATE_TEST_SUITE_P(ByDevice, AllTranslationTableTest, ValuesIn(kDevices));
110
TEST(TranslationTableTest,Seed)111 TEST(TranslationTableTest, Seed) {
112 std::string path = base::GetTestDataPath(
113 "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/");
114 FtraceProcfs ftrace_procfs(path);
115 auto table = ProtoTranslationTable::Create(
116 &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
117 PERFETTO_CHECK(table);
118 const Field& pid_field = table->common_fields().at(0);
119 EXPECT_EQ(std::string(pid_field.ftrace_name), "common_pid");
120 EXPECT_EQ(pid_field.proto_field_id, 2u);
121 EXPECT_EQ(pid_field.ftrace_offset, 4u);
122 EXPECT_EQ(pid_field.ftrace_size, 4u);
123
124 {
125 auto event = table->GetEvent(GroupAndName("sched", "sched_switch"));
126 EXPECT_EQ(std::string(event->name), "sched_switch");
127 EXPECT_EQ(std::string(event->group), "sched");
128 EXPECT_EQ(event->ftrace_event_id, 68ul);
129 EXPECT_EQ(event->fields.at(0).ftrace_offset, 8u);
130 EXPECT_EQ(event->fields.at(0).ftrace_size, 16u);
131 }
132
133 {
134 auto event = table->GetEvent(GroupAndName("sched", "sched_wakeup"));
135 EXPECT_EQ(std::string(event->name), "sched_wakeup");
136 EXPECT_EQ(std::string(event->group), "sched");
137 EXPECT_EQ(event->ftrace_event_id, 70ul);
138 EXPECT_EQ(event->fields.at(0).ftrace_offset, 8u);
139 EXPECT_EQ(event->fields.at(0).ftrace_size, 16u);
140 }
141
142 {
143 auto event = table->GetEvent(GroupAndName("ext4", "ext4_da_write_begin"));
144 EXPECT_EQ(std::string(event->name), "ext4_da_write_begin");
145 EXPECT_EQ(std::string(event->group), "ext4");
146 EXPECT_EQ(event->ftrace_event_id, 303ul);
147 EXPECT_EQ(event->fields.at(0).ftrace_offset, 8u);
148 EXPECT_EQ(event->fields.at(0).ftrace_size, 4u);
149 }
150 }
151
TEST_P(TranslationTableCreationTest,Create)152 TEST_P(TranslationTableCreationTest, Create) {
153 MockFtraceProcfs ftrace;
154 std::vector<Field> common_fields;
155 std::vector<Event> events;
156
157 ON_CALL(ftrace, ReadPageHeaderFormat())
158 .WillByDefault(Return(
159 R"( field: u64 timestamp; offset:0; size:8; signed:0;
160 field: local_t commit; offset:8; size:)" +
161 std::to_string(GetParam()) + R"(; signed:1;
162 field: int overwrite; offset:8; size:1; signed:1;
163 field: char data; offset:16; size:4080; signed:0;)"));
164 ON_CALL(ftrace, ReadEventFormat(_, _)).WillByDefault(Return(""));
165 ON_CALL(ftrace, ReadEventFormat("group", "foo"))
166 .WillByDefault(Return(R"(name: foo
167 ID: 42
168 format:
169 field:unsigned short common_type; offset:0; size:2; signed:0;
170 field:int common_pid; offset:4; size:4; signed:1;
171
172 field:char field_a[16]; offset:8; size:16; signed:0;
173 field:int field_b; offset:24; size:4; signed:1;
174 field:int field_d; offset:28; size:4; signed:1;
175 field:u32 field_e; offset:32; size:4; signed:0;
176
177 print fmt: "some format")"));
178
179 EXPECT_CALL(ftrace, ReadPageHeaderFormat()).Times(AnyNumber());
180 EXPECT_CALL(ftrace, ReadEventFormat(_, _)).Times(AnyNumber());
181
182 {
183 events.emplace_back(Event{});
184 Event* event = &events.back();
185 event->name = "foo";
186 event->group = "group";
187 event->proto_field_id = 21;
188
189 {
190 // We should get this field.
191 event->fields.emplace_back(Field{});
192 Field* field = &event->fields.back();
193 field->proto_field_id = 501;
194 field->proto_field_type = ProtoSchemaType::kString;
195 field->ftrace_name = "field_a";
196 }
197
198 {
199 // We shouldn't get this field: don't know how to read int -> string.
200 event->fields.emplace_back(Field{});
201 Field* field = &event->fields.back();
202 field->proto_field_id = 502;
203 field->proto_field_type = ProtoSchemaType::kString;
204 field->ftrace_name = "field_b";
205 }
206
207 {
208 // We shouldn't get this field: no matching field in the format file.
209 event->fields.emplace_back(Field{});
210 Field* field = &event->fields.back();
211 field->proto_field_id = 503;
212 field->proto_field_type = ProtoSchemaType::kString;
213 field->ftrace_name = "field_c";
214 }
215
216 {
217 // We should get this field.
218 event->fields.emplace_back(Field{});
219 Field* field = &event->fields.back();
220 field->proto_field_id = 504;
221 field->proto_field_type = ProtoSchemaType::kUint64;
222 field->ftrace_name = "field_e";
223 }
224 }
225
226 {
227 events.emplace_back(Event{});
228 Event* event = &events.back();
229 event->name = "bar";
230 event->group = "group";
231 event->proto_field_id = 22;
232 }
233
234 auto table = ProtoTranslationTable::Create(&ftrace, std::move(events),
235 std::move(common_fields));
236 PERFETTO_CHECK(table);
237 EXPECT_EQ(table->largest_id(), 42ul);
238 EXPECT_EQ(table->EventToFtraceId(GroupAndName("group", "foo")), 42ul);
239 EXPECT_EQ(table->EventToFtraceId(GroupAndName("group", "bar")), 0ul);
240 EXPECT_FALSE(table->GetEventById(43ul));
241 ASSERT_TRUE(table->GetEventById(42ul));
242 EXPECT_EQ(table->ftrace_page_header_spec().timestamp.size, 8);
243 EXPECT_EQ(table->ftrace_page_header_spec().size.size, GetParam());
244 EXPECT_EQ(table->ftrace_page_header_spec().overwrite.size, 1);
245 auto event = table->GetEventById(42);
246 EXPECT_EQ(event->ftrace_event_id, 42ul);
247 EXPECT_EQ(event->proto_field_id, 21ul);
248 EXPECT_EQ(event->size, 36u);
249 EXPECT_EQ(std::string(event->name), "foo");
250 EXPECT_EQ(std::string(event->group), "group");
251
252 ASSERT_EQ(event->fields.size(), 2ul);
253 auto field_a = event->fields.at(0);
254 EXPECT_EQ(field_a.proto_field_id, 501ul);
255 EXPECT_EQ(field_a.strategy, kFixedCStringToString);
256
257 auto field_e = event->fields.at(1);
258 EXPECT_EQ(field_e.proto_field_id, 504ul);
259 EXPECT_EQ(field_e.strategy, kUint32ToUint64);
260 }
261
262 INSTANTIATE_TEST_SUITE_P(BySize, TranslationTableCreationTest, Values(4, 8));
263
TEST(TranslationTableTest,CompactSchedFormatParsingWalleyeData)264 TEST(TranslationTableTest, CompactSchedFormatParsingWalleyeData) {
265 std::string path =
266 "src/traced/probes/ftrace/test/data/"
267 "android_walleye_OPM5.171019.017.A1_4.4.88/";
268 FtraceProcfs ftrace_procfs(path);
269 auto table = ProtoTranslationTable::Create(
270 &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
271 PERFETTO_CHECK(table);
272 const CompactSchedEventFormat& format = table->compact_sched_format();
273
274 // Format matches compile-time assumptions.
275 ASSERT_TRUE(format.format_valid);
276
277 // Check exact sched_switch format (note: 64 bit long prev_state).
278 EXPECT_EQ(47u, format.sched_switch.event_id);
279 EXPECT_EQ(64u, format.sched_switch.size);
280 EXPECT_EQ(56u, format.sched_switch.next_pid_offset);
281 EXPECT_EQ(FtraceFieldType::kFtracePid32, format.sched_switch.next_pid_type);
282 EXPECT_EQ(60u, format.sched_switch.next_prio_offset);
283 EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_switch.next_prio_type);
284 EXPECT_EQ(32u, format.sched_switch.prev_state_offset);
285 EXPECT_EQ(FtraceFieldType::kFtraceInt64, format.sched_switch.prev_state_type);
286 EXPECT_EQ(40u, format.sched_switch.next_comm_offset);
287
288 // Check exact sched_waking format.
289 EXPECT_EQ(44u, format.sched_waking.event_id);
290 EXPECT_EQ(40u, format.sched_waking.size);
291 EXPECT_EQ(24u, format.sched_waking.pid_offset);
292 EXPECT_EQ(FtraceFieldType::kFtracePid32, format.sched_waking.pid_type);
293 EXPECT_EQ(36u, format.sched_waking.target_cpu_offset);
294 EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_waking.target_cpu_type);
295 EXPECT_EQ(28u, format.sched_waking.prio_offset);
296 EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_waking.prio_type);
297 EXPECT_EQ(8u, format.sched_waking.comm_offset);
298 }
299
TEST(TranslationTableTest,CompactSchedFormatParsingSeedData)300 TEST(TranslationTableTest, CompactSchedFormatParsingSeedData) {
301 std::string path =
302 "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/";
303 FtraceProcfs ftrace_procfs(path);
304 auto table = ProtoTranslationTable::Create(
305 &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
306 PERFETTO_CHECK(table);
307 const CompactSchedEventFormat& format = table->compact_sched_format();
308
309 // We consider the entire format invalid as there's no sched_waking event
310 // available. This is a simplifying assumption. We could instead look at each
311 // event independently (and in this case, sched_switch does match compile-time
312 // assumptions).
313 ASSERT_FALSE(format.format_valid);
314 }
315
TEST(TranslationTableTest,InferFtraceType)316 TEST(TranslationTableTest, InferFtraceType) {
317 FtraceFieldType type;
318
319 ASSERT_TRUE(InferFtraceType("char foo[16]", 16, false, &type));
320 EXPECT_EQ(type, kFtraceFixedCString);
321
322 ASSERT_TRUE(InferFtraceType("char[] foo", 8, false, &type));
323 EXPECT_EQ(type, kFtraceStringPtr);
324
325 ASSERT_TRUE(InferFtraceType("char * foo", 8, false, &type));
326 EXPECT_EQ(type, kFtraceStringPtr);
327
328 ASSERT_TRUE(InferFtraceType("char foo[64]", 64, false, &type));
329 EXPECT_EQ(type, kFtraceFixedCString);
330
331 ASSERT_TRUE(InferFtraceType("u32 foo", 4, false, &type));
332 EXPECT_EQ(type, kFtraceUint32);
333
334 ASSERT_TRUE(InferFtraceType("i_ino foo", 4, false, &type));
335 ASSERT_EQ(type, kFtraceInode32);
336
337 ASSERT_TRUE(InferFtraceType("i_ino foo", 8, false, &type));
338 ASSERT_EQ(type, kFtraceInode64);
339
340 ASSERT_TRUE(InferFtraceType("ino_t foo", 4, false, &type));
341 ASSERT_EQ(type, kFtraceInode32);
342
343 ASSERT_TRUE(InferFtraceType("ino_t foo", 8, false, &type));
344 ASSERT_EQ(type, kFtraceInode64);
345
346 ASSERT_TRUE(InferFtraceType("dev_t foo", 4, false, &type));
347 ASSERT_EQ(type, kFtraceDevId32);
348
349 ASSERT_TRUE(InferFtraceType("dev_t foo", 8, false, &type));
350 ASSERT_EQ(type, kFtraceDevId64);
351
352 ASSERT_TRUE(InferFtraceType("pid_t foo", 4, false, &type));
353 ASSERT_EQ(type, kFtracePid32);
354
355 ASSERT_TRUE(InferFtraceType("int common_pid", 4, false, &type));
356 ASSERT_EQ(type, kFtraceCommonPid32);
357
358 ASSERT_TRUE(InferFtraceType("char foo", 1, true, &type));
359 ASSERT_EQ(type, kFtraceInt8);
360
361 ASSERT_TRUE(InferFtraceType("__data_loc char[] foo", 4, false, &type));
362 ASSERT_EQ(type, kFtraceDataLoc);
363 ASSERT_FALSE(InferFtraceType("__data_loc char[] foo", 8, false, &type));
364
365 EXPECT_FALSE(InferFtraceType("foo", 64, false, &type));
366 }
367
TEST(TranslationTableTest,Getters)368 TEST(TranslationTableTest, Getters) {
369 MockFtraceProcfs ftrace;
370 std::vector<Field> common_fields;
371 std::vector<Event> events;
372
373 {
374 Event event;
375 event.name = "foo";
376 event.group = "group_one";
377 event.ftrace_event_id = 1;
378 events.push_back(event);
379 }
380
381 {
382 Event event;
383 event.name = "bar";
384 event.group = "group_one";
385 event.ftrace_event_id = 2;
386 events.push_back(event);
387 }
388
389 {
390 Event event;
391 event.name = "baz";
392 event.group = "group_two";
393 event.ftrace_event_id = 100;
394 events.push_back(event);
395 }
396
397 ProtoTranslationTable table(
398 &ftrace, events, std::move(common_fields),
399 ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
400 InvalidCompactSchedEventFormatForTesting());
401
402 EXPECT_EQ(table.largest_id(), 100ul);
403 EXPECT_EQ(table.EventToFtraceId(GroupAndName("group_one", "foo")), 1ul);
404 EXPECT_EQ(table.EventToFtraceId(GroupAndName("group_two", "baz")), 100ul);
405 EXPECT_EQ(table.EventToFtraceId(GroupAndName("group_one", "no_such_event")),
406 0ul);
407 EXPECT_EQ(table.GetEventById(1)->name, "foo");
408 EXPECT_EQ(table.GetEventById(3), nullptr);
409 EXPECT_EQ(table.GetEventById(200), nullptr);
410 EXPECT_EQ(table.GetEventById(0), nullptr);
411 EXPECT_EQ(table.GetEvent(GroupAndName("group_one", "foo"))->ftrace_event_id,
412 1u);
413 EXPECT_THAT(*table.GetEventsByGroup("group_one"),
414 Contains(testing::Field(&Event::name, "foo")));
415 EXPECT_THAT(*table.GetEventsByGroup("group_one"),
416 Contains(testing::Field(&Event::name, "bar")));
417 EXPECT_THAT(*table.GetEventsByGroup("group_two"),
418 Contains(testing::Field(&Event::name, "baz")));
419 EXPECT_THAT(table.GetEventsByGroup("group_three"), IsNull());
420 }
421
TEST(TranslationTableTest,Generic)422 TEST(TranslationTableTest, Generic) {
423 MockFtraceProcfs ftrace;
424 std::vector<Field> common_fields;
425 std::vector<Event> events;
426
427 ON_CALL(ftrace, ReadPageHeaderFormat())
428 .WillByDefault(Return(
429 R"( field: u64 timestamp; offset:0; size:8; signed:0;
430 field: local_t commit; offset:8; size:4; signed:1;
431 field: int overwrite; offset:8; size:1; signed:1;
432 field: char data; offset:16; size:4080; signed:0;)"));
433 ON_CALL(ftrace, ReadEventFormat(_, _)).WillByDefault(Return(""));
434 ON_CALL(ftrace, ReadEventFormat("group", "foo"))
435 .WillByDefault(Return(R"(name: foo
436 ID: 42
437 format:
438 field:unsigned short common_type; offset:0; size:2; signed:0;
439 field:int common_pid; offset:4; size:4; signed:1;
440
441 field:char field_a[16]; offset:8; size:16; signed:0;
442 field:bool field_b; offset:24; size:1; signed:0;
443 field:int field_c; offset:25; size:4; signed:1;
444 field:u32 field_d; offset:33; size:4; signed:0;
445
446 print fmt: "some format")"));
447
448 EXPECT_CALL(ftrace, ReadPageHeaderFormat()).Times(AnyNumber());
449 EXPECT_CALL(ftrace, ReadEventFormat(_, _)).Times(AnyNumber());
450
451 auto table = ProtoTranslationTable::Create(&ftrace, std::move(events),
452 std::move(common_fields));
453 PERFETTO_CHECK(table);
454 EXPECT_EQ(table->largest_id(), 0ul);
455 GroupAndName group_and_name("group", "foo");
456 const Event* e = table->GetOrCreateEvent(group_and_name);
457 EXPECT_EQ(table->largest_id(), 42ul);
458 EXPECT_EQ(table->EventToFtraceId(group_and_name), 42ul);
459
460 // Check getters
461 EXPECT_EQ(static_cast<int>(table->GetEventById(42)->proto_field_id),
462 protos::pbzero::FtraceEvent::kGenericFieldNumber);
463 EXPECT_EQ(static_cast<int>(table->GetEvent(group_and_name)->proto_field_id),
464 protos::pbzero::FtraceEvent::kGenericFieldNumber);
465 EXPECT_EQ(table->GetEventsByGroup("group")->front()->name,
466 group_and_name.name());
467
468 EXPECT_EQ(e->fields.size(), 4ul);
469 const std::vector<Field>& fields = e->fields;
470 // Check string field
471 const auto& str_field = fields[0];
472 EXPECT_STREQ(str_field.ftrace_name, "field_a");
473 EXPECT_EQ(static_cast<int>(str_field.proto_field_id),
474 protos::pbzero::GenericFtraceEvent::Field::kStrValueFieldNumber);
475 EXPECT_EQ(str_field.proto_field_type, ProtoSchemaType::kString);
476 EXPECT_EQ(str_field.ftrace_type, kFtraceFixedCString);
477 EXPECT_EQ(str_field.ftrace_size, 16);
478 EXPECT_EQ(str_field.ftrace_offset, 8);
479
480 // Check bool field
481 const auto& bool_field = fields[1];
482 EXPECT_STREQ(bool_field.ftrace_name, "field_b");
483 EXPECT_EQ(static_cast<int>(bool_field.proto_field_id),
484 protos::pbzero::GenericFtraceEvent::Field::kUintValueFieldNumber);
485 EXPECT_EQ(bool_field.proto_field_type, ProtoSchemaType::kUint64);
486 EXPECT_EQ(bool_field.ftrace_type, kFtraceBool);
487 EXPECT_EQ(bool_field.ftrace_size, 1);
488 EXPECT_EQ(bool_field.ftrace_offset, 24);
489
490 // Check int field
491 const auto& int_field = fields[2];
492 EXPECT_STREQ(int_field.ftrace_name, "field_c");
493 EXPECT_EQ(static_cast<int>(int_field.proto_field_id),
494 protos::pbzero::GenericFtraceEvent::Field::kIntValueFieldNumber);
495 EXPECT_EQ(int_field.proto_field_type, ProtoSchemaType::kInt64);
496 EXPECT_EQ(int_field.ftrace_type, kFtraceInt32);
497 EXPECT_EQ(int_field.ftrace_size, 4);
498 EXPECT_EQ(int_field.ftrace_offset, 25);
499
500 // Check uint field
501 const auto& uint_field = fields[3];
502 EXPECT_STREQ(uint_field.ftrace_name, "field_d");
503 EXPECT_EQ(static_cast<int>(uint_field.proto_field_id),
504 protos::pbzero::GenericFtraceEvent::Field::kUintValueFieldNumber);
505 EXPECT_EQ(uint_field.proto_field_type, ProtoSchemaType::kUint64);
506 EXPECT_EQ(uint_field.ftrace_type, kFtraceUint32);
507 EXPECT_EQ(uint_field.ftrace_size, 4);
508 EXPECT_EQ(uint_field.ftrace_offset, 33);
509 }
510
TEST(EventFilterTest,EnableEventsFrom)511 TEST(EventFilterTest, EnableEventsFrom) {
512 EventFilter filter;
513 filter.AddEnabledEvent(1);
514 filter.AddEnabledEvent(17);
515
516 EventFilter or_filter;
517 or_filter.AddEnabledEvent(4);
518 or_filter.AddEnabledEvent(17);
519
520 filter.EnableEventsFrom(or_filter);
521 EXPECT_TRUE(filter.IsEventEnabled(4));
522 EXPECT_TRUE(filter.IsEventEnabled(17));
523 EXPECT_TRUE(filter.IsEventEnabled(1));
524 EXPECT_FALSE(filter.IsEventEnabled(2));
525
526 EventFilter empty_filter;
527 filter.EnableEventsFrom(empty_filter);
528 EXPECT_TRUE(filter.IsEventEnabled(4));
529 EXPECT_TRUE(filter.IsEventEnabled(17));
530 EXPECT_TRUE(filter.IsEventEnabled(1));
531
532 empty_filter.EnableEventsFrom(filter);
533 EXPECT_TRUE(empty_filter.IsEventEnabled(4));
534 EXPECT_TRUE(empty_filter.IsEventEnabled(17));
535 EXPECT_TRUE(empty_filter.IsEventEnabled(1));
536 }
537
538 } // namespace
539 } // namespace perfetto
540