blob: 8edb4143eedfea496e2b7b6373cf15c0c6d6ff25 [file] [log] [blame]
Biswarup Pala0ae40f2023-11-15 13:30:48 +00001/*
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
42void PrintTo(const PerfettoPbDecoderField& field, std::ostream*);
43
44namespace perfetto {
45namespace shlib {
46namespace test_utils {
47
48class WaitableEvent {
49 public:
50 WaitableEvent() = default;
51 void Notify() {
52 std::unique_lock<std::mutex> lock(m_);
53 notified_ = true;
54 cv_.notify_one();
55 }
56 bool WaitForNotification() {
57 std::unique_lock<std::mutex> lock(m_);
58 cv_.wait(lock, [this] { return notified_; });
59 return notified_;
60 }
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
72class TracingSession {
73 public:
74 class Builder {
75 public:
76 Builder() = default;
Biswarup Pala0ae40f2023-11-15 13:30:48 +000077 Builder& add_enabled_category(std::string category) {
78 enabled_categories_.push_back(std::move(category));
79 return *this;
80 }
81 Builder& add_disabled_category(std::string category) {
82 disabled_categories_.push_back(std::move(category));
83 return *this;
84 }
Zimuzo Ezeozue32bd1522024-05-09 03:25:54 +010085 Builder& add_atrace_category(std::string category) {
86 atrace_categories_.push_back(std::move(category));
87 return *this;
88 }
89 Builder& add_atrace_category_prefer_sdk(std::string category) {
90 atrace_categories_prefer_sdk_.push_back(std::move(category));
91 return *this;
92 }
Biswarup Pala0ae40f2023-11-15 13:30:48 +000093 TracingSession Build();
94
95 private:
Biswarup Pala0ae40f2023-11-15 13:30:48 +000096 std::vector<std::string> enabled_categories_;
97 std::vector<std::string> disabled_categories_;
Zimuzo Ezeozue32bd1522024-05-09 03:25:54 +010098 std::vector<std::string> atrace_categories_;
99 std::vector<std::string> atrace_categories_prefer_sdk_;
Biswarup Pala0ae40f2023-11-15 13:30:48 +0000100 };
101
102 static TracingSession Adopt(struct PerfettoTracingSessionImpl*);
103
104 TracingSession(TracingSession&&) noexcept;
105
106 ~TracingSession();
107
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
123template <typename FieldSkipper>
124class 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:
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 }
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>
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>
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>
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 }
213 Iterator begin() const {
214 return Iterator(begin_, end_, s_);
215 }
216 Iterator end() const {
217 return Iterator(end_, end_, s_);
218 }
219 PerfettoPbDecoderField front() const {
220 return *begin();
221 }
222
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
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
248template <typename FieldSkipper>
249void 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
259class IdFieldSkipper {
260 public:
261 explicit IdFieldSkipper(uint32_t id) : id_(id) {
262 }
263 explicit IdFieldSkipper(int32_t id) : id_(static_cast<uint32_t>(id)) {
264 }
265 bool ShouldSkip(const struct PerfettoPbDecoderField& field) const {
266 return field.id != id_;
267 }
268
269 private:
270 uint32_t id_;
271};
272
273class NoFieldSkipper {
274 public:
275 NoFieldSkipper() = default;
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.
292using 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)
299using 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)));
307template <typename M>
308auto 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(...)));
320template <typename M>
321auto 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"));
336template <typename M>
337auto 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)));
355template <typename M>
356auto 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)));
372template <typename M>
373auto 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)));
389template <typename M>
390auto 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)));
406template <typename M>
407auto 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)));
423template <typename M>
424auto 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(...)));
441template <typename M>
442auto 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