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;
set_data_source_name(std::string data_source_name)77     Builder& set_data_source_name(std::string data_source_name) {
78       data_source_name_ = std::move(data_source_name);
79       return *this;
80     }
add_enabled_category(std::string category)81     Builder& add_enabled_category(std::string category) {
82       enabled_categories_.push_back(std::move(category));
83       return *this;
84     }
add_disabled_category(std::string category)85     Builder& add_disabled_category(std::string category) {
86       disabled_categories_.push_back(std::move(category));
87       return *this;
88     }
89     TracingSession Build();
90 
91    private:
92     std::string data_source_name_;
93     std::vector<std::string> enabled_categories_;
94     std::vector<std::string> disabled_categories_;
95   };
96 
97   static TracingSession Adopt(struct PerfettoTracingSessionImpl*);
98 
99   TracingSession(TracingSession&&) noexcept;
100 
101   ~TracingSession();
102 
session()103   struct PerfettoTracingSessionImpl* session() const {
104     return session_;
105   }
106 
107   bool FlushBlocking(uint32_t timeout_ms);
108   void 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, const uint8_t* end_ptr,
162              const FieldSkipper& skipper)
163         : read_ptr_(read_ptr), end_ptr_(end_ptr), skipper_(skipper) {
164       AdvanceToFirstInterestingField();
165     }
AdvanceToFirstInterestingField()166     void AdvanceToFirstInterestingField() {
167       struct PerfettoPbDecoder decoder;
168       decoder.read_ptr = read_ptr_;
169       decoder.end_ptr = end_ptr_;
170       struct PerfettoPbDecoderField field;
171       const uint8_t* prev_read_ptr;
172       do {
173         prev_read_ptr = decoder.read_ptr;
174         field = PerfettoPbDecoderParseField(&decoder);
175       } while (field.status == PERFETTO_PB_DECODER_OK &&
176                skipper_.ShouldSkip(field));
177       if (field.status == PERFETTO_PB_DECODER_OK) {
178         read_ptr_ = prev_read_ptr;
179       } else {
180         read_ptr_ = decoder.read_ptr;
181       }
182     }
183     friend class FieldViewBase<FieldSkipper>;
184     const uint8_t* read_ptr_;
185     const uint8_t* end_ptr_;
186     const FieldSkipper& skipper_;
187   };
188   using value_type = const PerfettoPbDecoderField;
189   using const_iterator = Iterator;
190   template <typename... Args>
FieldViewBase(const uint8_t * begin,const uint8_t * end,Args...args)191   explicit FieldViewBase(const uint8_t* begin, const uint8_t* end, Args... args)
192       : begin_(begin), end_(end), s_(args...) {
193   }
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   }
198   template <typename... Args>
FieldViewBase(const struct PerfettoPbDecoderField & field,Args...args)199   explicit FieldViewBase(const struct PerfettoPbDecoderField& field,
200                          Args... args)
201       : s_(args...) {
202     if (field.wire_type != PERFETTO_PB_WIRE_TYPE_DELIMITED) {
203       abort();
204     }
205     begin_ = field.value.delimited.start;
206     end_ = begin_ + field.value.delimited.len;
207   }
begin()208   Iterator begin() const {
209     return Iterator(begin_, end_, s_);
210   }
end()211   Iterator end() const {
212     return Iterator(end_, end_, s_);
213   }
front()214   PerfettoPbDecoderField front() const {
215     return *begin();
216   }
217 
size()218   size_t size() const {
219     size_t count = 0;
220     for (auto field : *this) {
221       (void)field;
222       count++;
223     }
224     return count;
225   }
226 
ok()227   bool ok() const {
228     for (auto field : *this) {
229       if (field.status != PERFETTO_PB_DECODER_OK) {
230         return false;
231       }
232     }
233     return true;
234   }
235 
236  private:
237   const uint8_t* begin_;
238   const uint8_t* end_;
239   FieldSkipper s_;
240 };
241 
242 // Pretty printer for gtest
243 template <typename FieldSkipper>
PrintTo(const FieldViewBase<FieldSkipper> & field_view,std::ostream * pos)244 void PrintTo(const FieldViewBase<FieldSkipper>& field_view, std::ostream* pos) {
245   std::ostream& os = *pos;
246   os << "{";
247   for (PerfettoPbDecoderField f : field_view) {
248     PrintTo(f, pos);
249     os << ", ";
250   }
251   os << "}";
252 }
253 
254 class IdFieldSkipper {
255  public:
IdFieldSkipper(uint32_t id)256   explicit IdFieldSkipper(uint32_t id) : id_(id) {
257   }
IdFieldSkipper(int32_t id)258   explicit IdFieldSkipper(int32_t id) : id_(static_cast<uint32_t>(id)) {
259   }
ShouldSkip(const struct PerfettoPbDecoderField & field)260   bool ShouldSkip(const struct PerfettoPbDecoderField& field) const {
261     return field.id != id_;
262   }
263 
264  private:
265   uint32_t id_;
266 };
267 
268 class NoFieldSkipper {
269  public:
270   NoFieldSkipper() = default;
ShouldSkip(const struct PerfettoPbDecoderField &)271   bool ShouldSkip(const struct PerfettoPbDecoderField&) const {
272     return false;
273   }
274 };
275 
276 // View over all the fields of a contiguous serialized protobuf message.
277 //
278 // Examples:
279 //
280 // for (struct PerfettoPbDecoderField field : FieldView(msg_begin, msg_end)) {
281 //   //...
282 // }
283 // FieldView fields2(/*PerfettoPbDecoderField*/ nested_field);
284 // FieldView fields3(/*std::vector<uint8_t>*/ data);
285 // size_t num = fields1.size(); // The number of fields.
286 // bool ok = fields1.ok(); // Checks that the message is not malformed.
287 using FieldView = FieldViewBase<NoFieldSkipper>;
288 
289 // Like `FieldView`, but only considers fields with a specific id.
290 //
291 // Examples:
292 //
293 // IdFieldView fields(msg_begin, msg_end, id)
294 using IdFieldView = FieldViewBase<IdFieldSkipper>;
295 
296 // Matches a PerfettoPbDecoderField with the specified id. Accepts another
297 // matcher to match the contents of the field.
298 //
299 // Example:
300 // PerfettoPbDecoderField field = ...
301 // EXPECT_THAT(field, PbField(900, VarIntField(5)));
302 template <typename M>
PbField(int32_t id,M m)303 auto PbField(int32_t id, M m) {
304   return testing::AllOf(
305       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
306       testing::Field(&PerfettoPbDecoderField::id, id), m);
307 }
308 
309 // Matches a PerfettoPbDecoderField submessage field. Accepts a container
310 // matcher for the subfields.
311 //
312 // Example:
313 // PerfettoPbDecoderField field = ...
314 // EXPECT_THAT(field, MsgField(ElementsAre(...)));
315 template <typename M>
MsgField(M m)316 auto MsgField(M m) {
317   auto f = [](const PerfettoPbDecoderField& field) { return FieldView(field); };
318   return testing::AllOf(
319       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
320       testing::Field(&PerfettoPbDecoderField::wire_type,
321                      PERFETTO_PB_WIRE_TYPE_DELIMITED),
322       testing::ResultOf(f, m));
323 }
324 
325 // Matches a PerfettoPbDecoderField length delimited field. Accepts a string
326 // matcher.
327 //
328 // Example:
329 // PerfettoPbDecoderField field = ...
330 // EXPECT_THAT(field, StringField("string"));
331 template <typename M>
StringField(M m)332 auto StringField(M m) {
333   auto f = [](const PerfettoPbDecoderField& field) {
334     return std::string(
335         reinterpret_cast<const char*>(field.value.delimited.start),
336         field.value.delimited.len);
337   };
338   return testing::AllOf(
339       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
340       testing::Field(&PerfettoPbDecoderField::wire_type,
341                      PERFETTO_PB_WIRE_TYPE_DELIMITED),
342       testing::ResultOf(f, m));
343 }
344 
345 // Matches a PerfettoPbDecoderField VarInt field. Accepts an integer matcher
346 //
347 // Example:
348 // PerfettoPbDecoderField field = ...
349 // EXPECT_THAT(field, VarIntField(1)));
350 template <typename M>
VarIntField(M m)351 auto VarIntField(M m) {
352   auto f = [](const PerfettoPbDecoderField& field) {
353     return field.value.integer64;
354   };
355   return testing::AllOf(
356       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
357       testing::Field(&PerfettoPbDecoderField::wire_type,
358                      PERFETTO_PB_WIRE_TYPE_VARINT),
359       testing::ResultOf(f, m));
360 }
361 
362 // Matches a PerfettoPbDecoderField fixed64 field. Accepts an integer matcher
363 //
364 // Example:
365 // PerfettoPbDecoderField field = ...
366 // EXPECT_THAT(field, Fixed64Field(1)));
367 template <typename M>
Fixed64Field(M m)368 auto Fixed64Field(M m) {
369   auto f = [](const PerfettoPbDecoderField& field) {
370     return field.value.integer64;
371   };
372   return testing::AllOf(
373       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
374       testing::Field(&PerfettoPbDecoderField::wire_type,
375                      PERFETTO_PB_WIRE_TYPE_FIXED64),
376       testing::ResultOf(f, m));
377 }
378 
379 // Matches a PerfettoPbDecoderField fixed32 field. Accepts an integer matcher
380 //
381 // Example:
382 // PerfettoPbDecoderField field = ...
383 // EXPECT_THAT(field, Fixed32Field(1)));
384 template <typename M>
Fixed32Field(M m)385 auto Fixed32Field(M m) {
386   auto f = [](const PerfettoPbDecoderField& field) {
387     return field.value.integer32;
388   };
389   return testing::AllOf(
390       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
391       testing::Field(&PerfettoPbDecoderField::wire_type,
392                      PERFETTO_PB_WIRE_TYPE_FIXED32),
393       testing::ResultOf(f, m));
394 }
395 
396 // Matches a PerfettoPbDecoderField double field. Accepts a double matcher
397 //
398 // Example:
399 // PerfettoPbDecoderField field = ...
400 // EXPECT_THAT(field, DoubleField(1.0)));
401 template <typename M>
DoubleField(M m)402 auto DoubleField(M m) {
403   auto f = [](const PerfettoPbDecoderField& field) {
404     return field.value.double_val;
405   };
406   return testing::AllOf(
407       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
408       testing::Field(&PerfettoPbDecoderField::wire_type,
409                      PERFETTO_PB_WIRE_TYPE_FIXED64),
410       testing::ResultOf(f, m));
411 }
412 
413 // Matches a PerfettoPbDecoderField float field. Accepts a float matcher
414 //
415 // Example:
416 // PerfettoPbDecoderField field = ...
417 // EXPECT_THAT(field, FloatField(1.0)));
418 template <typename M>
FloatField(M m)419 auto FloatField(M m) {
420   auto f = [](const PerfettoPbDecoderField& field) {
421     return field.value.float_val;
422   };
423   return testing::AllOf(
424       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
425       testing::Field(&PerfettoPbDecoderField::wire_type,
426                      PERFETTO_PB_WIRE_TYPE_FIXED32),
427       testing::ResultOf(f, m));
428 }
429 
430 // Matches a PerfettoPbDecoderField submessage field. Accepts a container
431 // matcher for the subfields.
432 //
433 // Example:
434 // PerfettoPbDecoderField field = ...
435 // EXPECT_THAT(field, AllFieldsWithId(900, ElementsAre(...)));
436 template <typename M>
AllFieldsWithId(int32_t id,M m)437 auto AllFieldsWithId(int32_t id, M m) {
438   auto f = [id](const PerfettoPbDecoderField& field) {
439     return IdFieldView(field, id);
440   };
441   return testing::AllOf(
442       testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
443       testing::Field(&PerfettoPbDecoderField::wire_type,
444                      PERFETTO_PB_WIRE_TYPE_DELIMITED),
445       testing::ResultOf(f, m));
446 }
447 
448 }  // namespace test_utils
449 }  // namespace shlib
450 }  // namespace perfetto
451 
452 #endif  // UTILS_H
453