1 /*
2 * Copyright (C) 2023 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 #ifndef SRC_SHARED_LIB_TEST_UTILS_H_
18 #define SRC_SHARED_LIB_TEST_UTILS_H_
19
20 #include <cassert>
21 #include <condition_variable>
22 #include <cstdint>
23 #include <functional>
24 #include <iterator>
25 #include <memory>
26 #include <mutex>
27 #include <ostream>
28 #include <string>
29 #include <vector>
30
31 #include "perfetto/public/abi/pb_decoder_abi.h"
32 #include "perfetto/public/pb_utils.h"
33 #include "perfetto/public/tracing_session.h"
34
35 #include "test/gtest_and_gmock.h"
36
37 // Pretty printer for gtest
38 void PrintTo(const PerfettoPbDecoderField& field, std::ostream*);
39
40 namespace perfetto {
41 namespace shlib {
42 namespace test_utils {
43
44 class WaitableEvent {
45 public:
46 WaitableEvent() = default;
Notify()47 void Notify() {
48 std::unique_lock<std::mutex> lock(m_);
49 notified_ = true;
50 cv_.notify_one();
51 }
WaitForNotification()52 bool WaitForNotification() {
53 std::unique_lock<std::mutex> lock(m_);
54 cv_.wait(lock, [this] { return notified_; });
55 return notified_;
56 }
IsNotified()57 bool IsNotified() {
58 std::unique_lock<std::mutex> lock(m_);
59 return notified_;
60 }
61
62 private:
63 std::mutex m_;
64 std::condition_variable cv_;
65 bool notified_ = false;
66 };
67
68 class TracingSession {
69 public:
70 class Builder {
71 public:
72 Builder() = default;
set_data_source_name(std::string data_source_name)73 Builder& set_data_source_name(std::string data_source_name) {
74 data_source_name_ = std::move(data_source_name);
75 return *this;
76 }
add_enabled_category(std::string category)77 Builder& add_enabled_category(std::string category) {
78 enabled_categories_.push_back(std::move(category));
79 return *this;
80 }
add_disabled_category(std::string category)81 Builder& add_disabled_category(std::string category) {
82 disabled_categories_.push_back(std::move(category));
83 return *this;
84 }
85 std::vector<uint8_t> BuildProtoConfig();
86
87 TracingSession Build();
88
89 private:
90 std::string data_source_name_;
91 std::vector<std::string> enabled_categories_;
92 std::vector<std::string> disabled_categories_;
93 };
94
95 static TracingSession Adopt(struct PerfettoTracingSessionImpl*);
96
97 TracingSession(TracingSession&&) noexcept;
98
99 ~TracingSession();
100
session()101 struct PerfettoTracingSessionImpl* session() const { return session_; }
102
103 bool FlushBlocking(uint32_t timeout_ms);
104 // Waits for the tracing session to be stopped.
105 void WaitForStopped();
106 // Asks the tracing session to stop. Doesn't wait for it to be stopped.
107 void StopAsync();
108 // Equivalent to StopAsync() + WaitForStopped().
109 void StopBlocking();
110 std::vector<uint8_t> ReadBlocking();
111
112 private:
113 TracingSession() = default;
114 struct PerfettoTracingSessionImpl* session_;
115 std::unique_ptr<WaitableEvent> stopped_;
116 };
117
118 template <typename FieldSkipper>
119 class FieldViewBase {
120 public:
121 class Iterator {
122 public:
123 using iterator_category = std::input_iterator_tag;
124 using value_type = const PerfettoPbDecoderField;
125 using pointer = value_type;
126 using reference = value_type;
127 reference operator*() const {
128 struct PerfettoPbDecoder decoder;
129 decoder.read_ptr = read_ptr_;
130 decoder.end_ptr = end_ptr_;
131 struct PerfettoPbDecoderField field;
132 do {
133 field = PerfettoPbDecoderParseField(&decoder);
134 } while (field.status == PERFETTO_PB_DECODER_OK &&
135 skipper_.ShouldSkip(field));
136 return field;
137 }
138 Iterator& operator++() {
139 struct PerfettoPbDecoder decoder;
140 decoder.read_ptr = read_ptr_;
141 decoder.end_ptr = end_ptr_;
142 PerfettoPbDecoderSkipField(&decoder);
143 read_ptr_ = decoder.read_ptr;
144 AdvanceToFirstInterestingField();
145 return *this;
146 }
147 Iterator operator++(int) {
148 Iterator tmp = *this;
149 ++(*this);
150 return tmp;
151 }
152
153 friend bool operator==(const Iterator& a, const Iterator& b) {
154 return a.read_ptr_ == b.read_ptr_;
155 }
156 friend bool operator!=(const Iterator& a, const Iterator& b) {
157 return a.read_ptr_ != b.read_ptr_;
158 }
159
160 private:
Iterator(const uint8_t * read_ptr,const uint8_t * end_ptr,const FieldSkipper & skipper)161 Iterator(const uint8_t* read_ptr,
162 const uint8_t* end_ptr,
163 const FieldSkipper& skipper)
164 : read_ptr_(read_ptr), end_ptr_(end_ptr), skipper_(skipper) {
165 AdvanceToFirstInterestingField();
166 }
AdvanceToFirstInterestingField()167 void AdvanceToFirstInterestingField() {
168 struct PerfettoPbDecoder decoder;
169 decoder.read_ptr = read_ptr_;
170 decoder.end_ptr = end_ptr_;
171 struct PerfettoPbDecoderField field;
172 const uint8_t* prev_read_ptr;
173 do {
174 prev_read_ptr = decoder.read_ptr;
175 field = PerfettoPbDecoderParseField(&decoder);
176 } while (field.status == PERFETTO_PB_DECODER_OK &&
177 skipper_.ShouldSkip(field));
178 if (field.status == PERFETTO_PB_DECODER_OK) {
179 read_ptr_ = prev_read_ptr;
180 } else {
181 read_ptr_ = decoder.read_ptr;
182 }
183 }
184 friend class FieldViewBase<FieldSkipper>;
185 const uint8_t* read_ptr_;
186 const uint8_t* end_ptr_;
187 const FieldSkipper& skipper_;
188 };
189 using value_type = const PerfettoPbDecoderField;
190 using const_iterator = Iterator;
191 template <typename... Args>
FieldViewBase(const uint8_t * begin,const uint8_t * end,Args...args)192 explicit FieldViewBase(const uint8_t* begin, const uint8_t* end, Args... args)
193 : begin_(begin), end_(end), s_(args...) {}
194 template <typename... Args>
FieldViewBase(const std::vector<uint8_t> & data,Args...args)195 explicit FieldViewBase(const std::vector<uint8_t>& data, Args... args)
196 : FieldViewBase(data.data(), data.data() + data.size(), args...) {}
197 template <typename... Args>
FieldViewBase(const struct PerfettoPbDecoderField & field,Args...args)198 explicit FieldViewBase(const struct PerfettoPbDecoderField& field,
199 Args... args)
200 : s_(args...) {
201 if (field.wire_type != PERFETTO_PB_WIRE_TYPE_DELIMITED) {
202 abort();
203 }
204 begin_ = field.value.delimited.start;
205 end_ = begin_ + field.value.delimited.len;
206 }
begin()207 Iterator begin() const { return Iterator(begin_, end_, s_); }
end()208 Iterator end() const { return Iterator(end_, end_, s_); }
front()209 PerfettoPbDecoderField front() const { return *begin(); }
210
size()211 size_t size() const {
212 size_t count = 0;
213 for (auto field : *this) {
214 (void)field;
215 count++;
216 }
217 return count;
218 }
219
ok()220 bool ok() const {
221 for (auto field : *this) {
222 if (field.status != PERFETTO_PB_DECODER_OK) {
223 return false;
224 }
225 }
226 return true;
227 }
228
229 private:
230 const uint8_t* begin_;
231 const uint8_t* end_;
232 FieldSkipper s_;
233 };
234
235 // Pretty printer for gtest
236 template <typename FieldSkipper>
PrintTo(const FieldViewBase<FieldSkipper> & field_view,std::ostream * pos)237 void PrintTo(const FieldViewBase<FieldSkipper>& field_view, std::ostream* pos) {
238 std::ostream& os = *pos;
239 os << "{";
240 for (PerfettoPbDecoderField f : field_view) {
241 PrintTo(f, pos);
242 os << ", ";
243 }
244 os << "}";
245 }
246
247 class IdFieldSkipper {
248 public:
IdFieldSkipper(uint32_t id)249 explicit IdFieldSkipper(uint32_t id) : id_(id) {}
IdFieldSkipper(int32_t id)250 explicit IdFieldSkipper(int32_t id) : id_(static_cast<uint32_t>(id)) {}
ShouldSkip(const struct PerfettoPbDecoderField & field)251 bool ShouldSkip(const struct PerfettoPbDecoderField& field) const {
252 return field.id != id_;
253 }
254
255 private:
256 uint32_t id_;
257 };
258
259 class NoFieldSkipper {
260 public:
261 NoFieldSkipper() = default;
ShouldSkip(const struct PerfettoPbDecoderField &)262 bool ShouldSkip(const struct PerfettoPbDecoderField&) const { return false; }
263 };
264
265 // View over all the fields of a contiguous serialized protobuf message.
266 //
267 // Examples:
268 //
269 // for (struct PerfettoPbDecoderField field : FieldView(msg_begin, msg_end)) {
270 // //...
271 // }
272 // FieldView fields2(/*PerfettoPbDecoderField*/ nested_field);
273 // FieldView fields3(/*std::vector<uint8_t>*/ data);
274 // size_t num = fields1.size(); // The number of fields.
275 // bool ok = fields1.ok(); // Checks that the message is not malformed.
276 using FieldView = FieldViewBase<NoFieldSkipper>;
277
278 // Like `FieldView`, but only considers fields with a specific id.
279 //
280 // Examples:
281 //
282 // IdFieldView fields(msg_begin, msg_end, id)
283 using IdFieldView = FieldViewBase<IdFieldSkipper>;
284
285 // Matches a PerfettoPbDecoderField with the specified id. Accepts another
286 // matcher to match the contents of the field.
287 //
288 // Example:
289 // PerfettoPbDecoderField field = ...
290 // EXPECT_THAT(field, PbField(900, VarIntField(5)));
291 template <typename M>
PbField(int32_t id,M m)292 auto PbField(int32_t id, M m) {
293 return testing::AllOf(
294 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
295 testing::Field(&PerfettoPbDecoderField::id, id), m);
296 }
297
298 // Matches a PerfettoPbDecoderField submessage field. Accepts a container
299 // matcher for the subfields.
300 //
301 // Example:
302 // PerfettoPbDecoderField field = ...
303 // EXPECT_THAT(field, MsgField(ElementsAre(...)));
304 template <typename M>
MsgField(M m)305 auto MsgField(M m) {
306 auto f = [](const PerfettoPbDecoderField& field) { return FieldView(field); };
307 return testing::AllOf(
308 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
309 testing::Field(&PerfettoPbDecoderField::wire_type,
310 PERFETTO_PB_WIRE_TYPE_DELIMITED),
311 testing::ResultOf(f, m));
312 }
313
314 // Matches a PerfettoPbDecoderField length delimited field. Accepts a string
315 // matcher.
316 //
317 // Example:
318 // PerfettoPbDecoderField field = ...
319 // EXPECT_THAT(field, StringField("string"));
320 template <typename M>
StringField(M m)321 auto StringField(M m) {
322 auto f = [](const PerfettoPbDecoderField& field) {
323 return std::string(
324 reinterpret_cast<const char*>(field.value.delimited.start),
325 field.value.delimited.len);
326 };
327 return testing::AllOf(
328 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
329 testing::Field(&PerfettoPbDecoderField::wire_type,
330 PERFETTO_PB_WIRE_TYPE_DELIMITED),
331 testing::ResultOf(f, m));
332 }
333
334 // Matches a PerfettoPbDecoderField VarInt field. Accepts an integer matcher
335 //
336 // Example:
337 // PerfettoPbDecoderField field = ...
338 // EXPECT_THAT(field, VarIntField(1)));
339 template <typename M>
VarIntField(M m)340 auto VarIntField(M m) {
341 auto f = [](const PerfettoPbDecoderField& field) {
342 return field.value.integer64;
343 };
344 return testing::AllOf(
345 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
346 testing::Field(&PerfettoPbDecoderField::wire_type,
347 PERFETTO_PB_WIRE_TYPE_VARINT),
348 testing::ResultOf(f, m));
349 }
350
351 // Matches a PerfettoPbDecoderField fixed64 field. Accepts an integer matcher
352 //
353 // Example:
354 // PerfettoPbDecoderField field = ...
355 // EXPECT_THAT(field, Fixed64Field(1)));
356 template <typename M>
Fixed64Field(M m)357 auto Fixed64Field(M m) {
358 auto f = [](const PerfettoPbDecoderField& field) {
359 return field.value.integer64;
360 };
361 return testing::AllOf(
362 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
363 testing::Field(&PerfettoPbDecoderField::wire_type,
364 PERFETTO_PB_WIRE_TYPE_FIXED64),
365 testing::ResultOf(f, m));
366 }
367
368 // Matches a PerfettoPbDecoderField fixed32 field. Accepts an integer matcher
369 //
370 // Example:
371 // PerfettoPbDecoderField field = ...
372 // EXPECT_THAT(field, Fixed32Field(1)));
373 template <typename M>
Fixed32Field(M m)374 auto Fixed32Field(M m) {
375 auto f = [](const PerfettoPbDecoderField& field) {
376 return field.value.integer32;
377 };
378 return testing::AllOf(
379 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
380 testing::Field(&PerfettoPbDecoderField::wire_type,
381 PERFETTO_PB_WIRE_TYPE_FIXED32),
382 testing::ResultOf(f, m));
383 }
384
385 // Matches a PerfettoPbDecoderField double field. Accepts an double matcher
386 //
387 // Example:
388 // PerfettoPbDecoderField field = ...
389 // EXPECT_THAT(field, DoubleField(1.0)));
390 template <typename M>
DoubleField(M m)391 auto DoubleField(M m) {
392 auto f = [](const PerfettoPbDecoderField& field) {
393 return field.value.double_val;
394 };
395 return testing::AllOf(
396 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
397 testing::Field(&PerfettoPbDecoderField::wire_type,
398 PERFETTO_PB_WIRE_TYPE_FIXED64),
399 testing::ResultOf(f, m));
400 }
401
402 // Matches a PerfettoPbDecoderField float field. Accepts a float matcher
403 //
404 // Example:
405 // PerfettoPbDecoderField field = ...
406 // EXPECT_THAT(field, FloatField(1.0)));
407 template <typename M>
FloatField(M m)408 auto FloatField(M m) {
409 auto f = [](const PerfettoPbDecoderField& field) {
410 return field.value.float_val;
411 };
412 return testing::AllOf(
413 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
414 testing::Field(&PerfettoPbDecoderField::wire_type,
415 PERFETTO_PB_WIRE_TYPE_FIXED32),
416 testing::ResultOf(f, m));
417 }
418
419 // Matches a PerfettoPbDecoderField submessage field. Accepts a container
420 // matcher for the subfields.
421 //
422 // Example:
423 // PerfettoPbDecoderField field = ...
424 // EXPECT_THAT(field, AllFieldsWithId(900, ElementsAre(...)));
425 template <typename M>
AllFieldsWithId(int32_t id,M m)426 auto AllFieldsWithId(int32_t id, M m) {
427 auto f = [id](const PerfettoPbDecoderField& field) {
428 return IdFieldView(field, id);
429 };
430 return testing::AllOf(
431 testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
432 testing::Field(&PerfettoPbDecoderField::wire_type,
433 PERFETTO_PB_WIRE_TYPE_DELIMITED),
434 testing::ResultOf(f, m));
435 }
436
437 } // namespace test_utils
438 } // namespace shlib
439 } // namespace perfetto
440
441 #endif // SRC_SHARED_LIB_TEST_UTILS_H_
442