xref: /aosp_15_r20/external/perfetto/src/trace_processor/util/trace_blob_view_reader_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 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 #include "src/trace_processor/util/trace_blob_view_reader.h"
18 
19 #include <algorithm>
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstring>
23 #include <optional>
24 #include <ostream>
25 #include <vector>
26 
27 #include "perfetto/trace_processor/trace_blob.h"
28 #include "perfetto/trace_processor/trace_blob_view.h"
29 #include "test/gtest_and_gmock.h"
30 
31 namespace perfetto::trace_processor::util {
32 namespace {
33 
34 using ::testing::ElementsAreArray;
35 using ::testing::Eq;
36 using ::testing::Optional;
37 using ::testing::Property;
38 using ::testing::SizeIs;
39 
40 class SameDataAsMatcher {
41  public:
42   template <typename ArgType>
43   class MatcherImpl : public ::testing ::MatcherInterface<const ArgType&> {
44    public:
MatcherImpl(const TraceBlobView & expected_data)45     explicit MatcherImpl(const TraceBlobView& expected_data)
46         : expected_data_(expected_data) {}
MatchAndExplain(const ArgType & arg,::testing::MatchResultListener *) const47     bool MatchAndExplain(const ArgType& arg,
48                          ::testing ::MatchResultListener*) const override {
49       return std::equal(expected_data_.data(),
50                         expected_data_.data() + expected_data_.size(),
51                         arg.data(), arg.data() + arg.size());
52     }
DescribeTo(::std::ostream *) const53     void DescribeTo(::std ::ostream*) const override {}
DescribeNegationTo(::std::ostream *) const54     void DescribeNegationTo(::std ::ostream*) const override {}
55 
56    private:
57     const TraceBlobView& expected_data_;
58   };
59 
SameDataAsMatcher(const TraceBlobView & expected_data)60   explicit SameDataAsMatcher(const TraceBlobView& expected_data)
61       : expected_data_(expected_data) {}
62 
63   template <typename ArgType>
operator ::testing::Matcher<ArgType>() const64   operator ::testing::Matcher<ArgType>() const {
65     return ::testing::Matcher<ArgType>(
66         new MatcherImpl<ArgType>(expected_data_));
67   }
68 
69  private:
70   const TraceBlobView& expected_data_;
71 };
72 
SameDataAs(const TraceBlobView & expected_data)73 SameDataAsMatcher SameDataAs(const TraceBlobView& expected_data) {
74   return SameDataAsMatcher(expected_data);
75 }
76 
CreateExpectedData(size_t expected_size)77 TraceBlobView CreateExpectedData(size_t expected_size) {
78   TraceBlob tb = TraceBlob::Allocate(expected_size);
79   for (size_t i = 0; i < expected_size; ++i) {
80     tb.data()[i] = static_cast<uint8_t>(i);
81   }
82   return TraceBlobView(std::move(tb));
83 }
84 
Slice(const TraceBlobView & blob,size_t chunk_size)85 std::vector<TraceBlobView> Slice(const TraceBlobView& blob, size_t chunk_size) {
86   std::vector<TraceBlobView> chunks;
87   size_t size = blob.size();
88   for (size_t off = 0; size != 0;) {
89     chunk_size = std::min(chunk_size, size);
90     chunks.push_back(blob.slice_off(off, chunk_size));
91     size -= chunk_size;
92     off += chunk_size;
93   }
94   return chunks;
95 }
96 
CreateTraceBlobViewReader(const std::vector<TraceBlobView> & chunks)97 TraceBlobViewReader CreateTraceBlobViewReader(
98     const std::vector<TraceBlobView>& chunks) {
99   TraceBlobViewReader chunked_buffer;
100   for (const auto& chunk : chunks) {
101     chunked_buffer.PushBack(chunk.copy());
102   }
103   return chunked_buffer;
104 }
105 
TEST(TraceBlobViewReader,ContiguousAccessAtOffset)106 TEST(TraceBlobViewReader, ContiguousAccessAtOffset) {
107   constexpr size_t kExpectedSize = 256;
108   constexpr size_t kChunkSize = kExpectedSize / 4;
109   TraceBlobView expected_data = CreateExpectedData(kExpectedSize);
110   TraceBlobViewReader buffer =
111       CreateTraceBlobViewReader(Slice(expected_data, kChunkSize));
112 
113   for (size_t file_offset = 0; file_offset <= kExpectedSize; ++file_offset) {
114     EXPECT_TRUE(buffer.PopFrontUntil(file_offset));
115     for (size_t off = file_offset; off <= kExpectedSize; ++off) {
116       auto expected = expected_data.slice_off(off, kExpectedSize - off);
117       std::optional<TraceBlobView> tbv = buffer.SliceOff(off, expected.size());
118       EXPECT_THAT(tbv, Optional(SameDataAs(expected)));
119     }
120   }
121 }
122 
TEST(TraceBlobViewReader,NoCopyIfDataIsContiguous)123 TEST(TraceBlobViewReader, NoCopyIfDataIsContiguous) {
124   constexpr size_t kExpectedSize = 256;
125   constexpr size_t kChunkSize = kExpectedSize / 4;
126   std::vector<TraceBlobView> chunks =
127       Slice(CreateExpectedData(kExpectedSize), kChunkSize);
128   TraceBlobViewReader buffer = CreateTraceBlobViewReader(chunks);
129 
130   for (size_t i = 0; i < chunks.size(); ++i) {
131     for (size_t off = 0; off < kChunkSize; ++off) {
132       const size_t expected_size = kChunkSize - off;
133       EXPECT_THAT(
134           buffer.SliceOff(i * kChunkSize + off, expected_size),
135           Optional(Property(&TraceBlobView::data, Eq(chunks[i].data() + off))));
136     }
137   }
138 }
139 
TEST(TraceBlobViewReader,PopRemovesData)140 TEST(TraceBlobViewReader, PopRemovesData) {
141   size_t expected_size = 256;
142   size_t expected_file_offset = 0;
143   const size_t kChunkSize = expected_size / 4;
144   TraceBlobView expected_data = CreateExpectedData(expected_size);
145   TraceBlobViewReader buffer =
146       CreateTraceBlobViewReader(Slice(expected_data, kChunkSize));
147 
148   --expected_size;
149   ++expected_file_offset;
150   buffer.PopFrontUntil(expected_file_offset);
151   EXPECT_THAT(buffer.start_offset(), Eq(expected_file_offset));
152   EXPECT_THAT(buffer.SliceOff(expected_file_offset, expected_size),
153               Optional(SameDataAs(expected_data.slice_off(
154                   expected_data.size() - expected_size, expected_size))));
155 
156   expected_size -= kChunkSize;
157   expected_file_offset += kChunkSize;
158   buffer.PopFrontUntil(expected_file_offset);
159   EXPECT_THAT(buffer.start_offset(), Eq(expected_file_offset));
160   EXPECT_THAT(buffer.SliceOff(expected_file_offset, expected_size),
161               Optional(SameDataAs(expected_data.slice_off(
162                   expected_data.size() - expected_size, expected_size))));
163 }
164 
165 }  // namespace
166 }  // namespace perfetto::trace_processor::util
167