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