• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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