blob: 435355496304a591e1a61ab1ae6f8dc441d1be17 [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;
77 Builder& set_data_source_name(std::string data_source_name) {
78 data_source_name_ = std::move(data_source_name);
79 return *this;
80 }
81 Builder& add_enabled_category(std::string category) {
82 enabled_categories_.push_back(std::move(category));
83 return *this;
84 }
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
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
118template <typename FieldSkipper>
119class 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:
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 }
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>
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>
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>
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 }
208 Iterator begin() const {
209 return Iterator(begin_, end_, s_);
210 }
211 Iterator end() const {
212 return Iterator(end_, end_, s_);
213 }
214 PerfettoPbDecoderField front() const {
215 return *begin();
216 }
217
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
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
243template <typename FieldSkipper>
244void 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
254class IdFieldSkipper {
255 public:
256 explicit IdFieldSkipper(uint32_t id) : id_(id) {
257 }
258 explicit IdFieldSkipper(int32_t id) : id_(static_cast<uint32_t>(id)) {
259 }
260 bool ShouldSkip(const struct PerfettoPbDecoderField& field) const {
261 return field.id != id_;
262 }
263
264 private:
265 uint32_t id_;
266};
267
268class NoFieldSkipper {
269 public:
270 NoFieldSkipper() = default;
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.
287using 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)
294using 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)));
302template <typename M>
303auto 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(...)));
315template <typename M>
316auto 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"));
331template <typename M>
332auto 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)));
350template <typename M>
351auto 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)));
367template <typename M>
368auto 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)));
384template <typename M>
385auto 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)));
401template <typename M>
402auto 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)));
418template <typename M>
419auto 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(...)));
436template <typename M>
437auto 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