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