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