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 #include "src/traced/probes/ftrace/format_parser.h"
17
18 #include "test/gtest_and_gmock.h"
19
20 namespace perfetto {
21 namespace {
22
23 using testing::ElementsAre;
24 using testing::Eq;
25
TEST(FtraceEventParserTest,HappyPath)26 TEST(FtraceEventParserTest, HappyPath) {
27 const std::string input = R"(name: the_name
28 ID: 42
29 format:
30 field:unsigned short common_type; offset:0; size:2; signed:0;
31 field:unsigned char common_flags; offset:2; size:1; signed:0;
32 field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
33 field:int common_pid; offset:4; size:4; signed:1;
34
35 field:char client_name[64]; offset:8; size:64; signed:0;
36 field:const char * heap_name; offset:72; size:4; signed:1;
37
38 print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
39 )";
40
41 FtraceEvent output;
42 EXPECT_TRUE(ParseFtraceEvent(input));
43 EXPECT_TRUE(ParseFtraceEvent(input, &output));
44 EXPECT_EQ(output.name, "the_name");
45 EXPECT_EQ(output.id, 42u);
46 EXPECT_THAT(
47 output.fields,
48 ElementsAre(
49 Eq(FtraceEvent::Field{"char client_name[64]", 8, 64, false}),
50 Eq(FtraceEvent::Field{"const char * heap_name", 72, 4, true})));
51 EXPECT_THAT(
52 output.common_fields,
53 ElementsAre(
54 Eq(FtraceEvent::Field{"unsigned short common_type", 0, 2, false}),
55 Eq(FtraceEvent::Field{"unsigned char common_flags", 2, 1, false}),
56 Eq(FtraceEvent::Field{"unsigned char common_preempt_count", 3, 1,
57 false}),
58 Eq(FtraceEvent::Field{"int common_pid", 4, 4, true})));
59 }
60
TEST(FtraceEventParserTest,MissingName)61 TEST(FtraceEventParserTest, MissingName) {
62 const std::string input = R"(ID: 42
63 format:
64 field:unsigned short common_type; offset:0; size:2; signed:0;
65 field:unsigned char common_flags; offset:2; size:1; signed:0;
66 field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
67 field:int common_pid; offset:4; size:4; signed:1;
68
69 print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
70 )";
71
72 EXPECT_FALSE(ParseFtraceEvent(input));
73 }
74
TEST(FtraceEventParserTest,MissingID)75 TEST(FtraceEventParserTest, MissingID) {
76 const std::string input = R"(name: the_name
77 format:
78 field:unsigned short common_type; offset:0; size:2; signed:0;
79 field:unsigned char common_flags; offset:2; size:1; signed:0;
80 field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
81 field:int common_pid; offset:4; size:4; signed:1;
82
83 print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
84 )";
85
86 EXPECT_FALSE(ParseFtraceEvent(input));
87 }
88
TEST(FtraceEventParserTest,NoFields)89 TEST(FtraceEventParserTest, NoFields) {
90 const std::string input = R"(name: the_name
91 ID: 10
92 print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
93 )";
94
95 EXPECT_FALSE(ParseFtraceEvent(input));
96 }
97
TEST(FtraceEventParserTest,BasicFuzzing)98 TEST(FtraceEventParserTest, BasicFuzzing) {
99 const std::string input = R"(name: the_name
100 ID: 42
101 format:
102 field:unsigned short common_type; offset:0; size:2; signed:0;
103 field:unsigned char common_flags; offset:2; size:1; signed:0;
104 field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
105 field:int common_pid; offset:4; size:4; signed:1;
106
107 field:char client_name[64]; offset:8; size:64; signed:0;
108 field:const char * heap_name; offset:72; size:4; signed:0;
109 field:size_t len; offset:76; size:4; signed:0;
110 field:unsigned int mask; offset:80; size:4; signed:0;
111 field:unsigned int flags; offset:84; size:4; signed:0;
112
113 print fmt: "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", REC->client_name, REC->heap_name, REC->len, REC->mask, REC->flags
114 )";
115
116 for (size_t i = 0; i < input.length(); i++) {
117 for (size_t j = 1; j < 10 && i + j < input.length(); j++) {
118 std::string copy = input;
119 copy.erase(i, j);
120 ParseFtraceEvent(copy);
121 }
122 }
123 }
124
TEST(FtraceEventParserTest,GetNameFromTypeAndName)125 TEST(FtraceEventParserTest, GetNameFromTypeAndName) {
126 EXPECT_EQ(GetNameFromTypeAndName("int foo"), "foo");
127 EXPECT_EQ(GetNameFromTypeAndName("int foo_bar"), "foo_bar");
128 EXPECT_EQ(GetNameFromTypeAndName("const char * foo"), "foo");
129 EXPECT_EQ(GetNameFromTypeAndName("const char foo[64]"), "foo");
130 EXPECT_EQ(GetNameFromTypeAndName("char[] foo[16]"), "foo");
131 EXPECT_EQ(GetNameFromTypeAndName("u8 foo[(int)sizeof(struct blah)]"), "foo");
132
133 EXPECT_EQ(GetNameFromTypeAndName(""), "");
134 EXPECT_EQ(GetNameFromTypeAndName("]"), "");
135 EXPECT_EQ(GetNameFromTypeAndName("["), "");
136 EXPECT_EQ(GetNameFromTypeAndName(" "), "");
137 EXPECT_EQ(GetNameFromTypeAndName(" []"), "");
138 EXPECT_EQ(GetNameFromTypeAndName(" ]["), "");
139 EXPECT_EQ(GetNameFromTypeAndName("char"), "");
140 EXPECT_EQ(GetNameFromTypeAndName("char *"), "");
141 EXPECT_EQ(GetNameFromTypeAndName("char 42"), "");
142 }
143
144 } // namespace
145 } // namespace perfetto
146