xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/perf/aux_stream_manager_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 #include "src/trace_processor/importers/perf/aux_stream_manager.h"
18 #include <cstdint>
19 #include <memory>
20 
21 #include "perfetto/base/status.h"
22 #include "perfetto/trace_processor/trace_blob.h"
23 #include "perfetto/trace_processor/trace_blob_view.h"
24 #include "src/trace_processor/importers/perf/aux_record.h"
25 #include "src/trace_processor/importers/perf/auxtrace_info_record.h"
26 #include "src/trace_processor/storage/stats.h"
27 #include "src/trace_processor/storage/trace_storage.h"
28 #include "src/trace_processor/types/trace_processor_context.h"
29 #include "test/gtest_and_gmock.h"
30 
31 namespace perfetto::trace_processor::perf_importer {
32 namespace {
33 
CreateTraceProcessorContext()34 std::unique_ptr<TraceProcessorContext> CreateTraceProcessorContext() {
35   auto ctx = std::make_unique<TraceProcessorContext>();
36   ctx->storage = std::make_shared<TraceStorage>();
37   return ctx;
38 }
39 
CreateAuxtraceInfoRecord()40 AuxtraceInfoRecord CreateAuxtraceInfoRecord() {
41   AuxtraceInfoRecord info;
42   info.type = 0;
43   return info;
44 }
45 
CreateAuxRecord(uint64_t offset,uint64_t size,uint32_t cpu)46 AuxRecord CreateAuxRecord(uint64_t offset, uint64_t size, uint32_t cpu) {
47   AuxRecord aux;
48   aux.offset = offset;
49   aux.size = size;
50   aux.flags = 0;
51   aux.sample_id.emplace();
52   aux.sample_id->set_cpu(cpu);
53   return aux;
54 }
55 
CreateAuxtraceRecord(uint64_t offset,uint64_t size,uint32_t cpu)56 AuxtraceRecord CreateAuxtraceRecord(uint64_t offset,
57                                     uint64_t size,
58                                     uint32_t cpu) {
59   AuxtraceRecord auxtrace;
60   auxtrace.offset = offset;
61   auxtrace.size = size;
62   auxtrace.cpu = cpu;
63   auxtrace.tid = 0;
64   return auxtrace;
65 }
66 
TEST(AuxStreamManagerTest,NoAuxStreamsCanFinalize)67 TEST(AuxStreamManagerTest, NoAuxStreamsCanFinalize) {
68   auto ctx = CreateTraceProcessorContext();
69   AuxStreamManager manager(ctx.get());
70   EXPECT_TRUE(manager.FinalizeStreams().ok());
71 }
72 
TEST(AuxStreamManagerTest,NoAuxTraceInfoFailsMethods)73 TEST(AuxStreamManagerTest, NoAuxTraceInfoFailsMethods) {
74   auto ctx = CreateTraceProcessorContext();
75   AuxStreamManager manager(ctx.get());
76 
77   EXPECT_FALSE(manager
78                    .OnAuxtraceRecord(CreateAuxtraceRecord(0, 10, 0),
79                                      TraceBlobView(TraceBlob::Allocate(10)))
80                    .ok());
81   EXPECT_FALSE(manager.OnAuxRecord(CreateAuxRecord(0, 10, 0)).ok());
82 }
83 
TEST(AuxStreamManagerTest,MultipleAuxTraceInfoFails)84 TEST(AuxStreamManagerTest, MultipleAuxTraceInfoFails) {
85   auto ctx = CreateTraceProcessorContext();
86   AuxStreamManager manager(ctx.get());
87 
88   AuxtraceInfoRecord info_0;
89   info_0.type = 0;
90   EXPECT_TRUE(manager.OnAuxtraceInfoRecord(std::move(info_0)).ok());
91 
92   AuxtraceInfoRecord info_1;
93   info_1.type = 1;
94   EXPECT_FALSE(manager.OnAuxtraceInfoRecord(std::move(info_1)).ok());
95 }
96 
TEST(AuxStreamManagerTest,ReconstructsStream)97 TEST(AuxStreamManagerTest, ReconstructsStream) {
98   constexpr uint64_t kSize = 10;
99   constexpr uint32_t kCpu = 0;
100   TraceBlobView data(TraceBlob::Allocate(kSize));
101   TraceBlobView double_data(TraceBlob::Allocate(2 * kSize));
102   auto ctx = CreateTraceProcessorContext();
103   AuxStreamManager manager(ctx.get());
104   ASSERT_TRUE(manager.OnAuxtraceInfoRecord(CreateAuxtraceInfoRecord()).ok());
105 
106   manager.OnAuxRecord(CreateAuxRecord(0, kSize, kCpu));
107   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 0);
108 
109   manager.OnAuxRecord(CreateAuxRecord(10, kSize, kCpu));
110   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 0);
111 
112   manager.OnAuxtraceRecord(CreateAuxtraceRecord(0, 2 * kSize, kCpu),
113                            double_data.copy());
114   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 20);
115 
116   manager.OnAuxtraceRecord(CreateAuxtraceRecord(20, kSize, kCpu), data.copy());
117   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 20);
118 
119   manager.OnAuxtraceRecord(CreateAuxtraceRecord(30, kSize, kCpu), data.copy());
120   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 20);
121 
122   manager.OnAuxRecord(CreateAuxRecord(20, 2 * kSize, kCpu));
123   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 40);
124 }
125 
TEST(AuxStreamManagerTest,AuxLoss)126 TEST(AuxStreamManagerTest, AuxLoss) {
127   constexpr uint64_t kSize = 10;
128   constexpr uint32_t kCpu = 0;
129   TraceBlobView data(TraceBlob::Allocate(kSize));
130   TraceBlobView triple_data(TraceBlob::Allocate(3 * kSize));
131   auto ctx = CreateTraceProcessorContext();
132   AuxStreamManager manager(ctx.get());
133   ASSERT_TRUE(manager.OnAuxtraceInfoRecord(CreateAuxtraceInfoRecord()).ok());
134 
135   manager.OnAuxRecord(CreateAuxRecord(10, kSize, kCpu));
136   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 10);
137   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 0);
138   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 0);
139   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 0);
140 
141   manager.OnAuxtraceRecord(CreateAuxtraceRecord(0, 3 * kSize, kCpu),
142                            triple_data.copy());
143   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 10);
144   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 0);
145   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 10);
146   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 10);
147 
148   manager.FinalizeStreams();
149   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 20);
150   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 0);
151   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 10);
152   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 20);
153 }
154 
TEST(AuxStreamManagerTest,AuxtraceLoss)155 TEST(AuxStreamManagerTest, AuxtraceLoss) {
156   constexpr uint64_t kSize = 10;
157   constexpr uint32_t kCpu = 0;
158   TraceBlobView data(TraceBlob::Allocate(kSize));
159   auto ctx = CreateTraceProcessorContext();
160   AuxStreamManager manager(ctx.get());
161   ASSERT_TRUE(manager.OnAuxtraceInfoRecord(CreateAuxtraceInfoRecord()).ok());
162 
163   manager.OnAuxtraceRecord(CreateAuxtraceRecord(10, kSize, kCpu), data.copy());
164   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 0);
165   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 10);
166   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 0);
167   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 0);
168 
169   manager.OnAuxRecord(CreateAuxRecord(0, 3 * kSize, kCpu));
170   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 0);
171   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 10);
172   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 10);
173   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 10);
174 
175   manager.FinalizeStreams();
176   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 0);
177   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 20);
178   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 10);
179   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 20);
180 }
181 
TEST(AuxStreamManagerTest,ComplexStream)182 TEST(AuxStreamManagerTest, ComplexStream) {
183   constexpr uint32_t kCpu = 0;
184   TraceBlobView data_5(TraceBlob::Allocate(5));
185   TraceBlobView data_10(TraceBlob::Allocate(10));
186   TraceBlobView data_15(TraceBlob::Allocate(15));
187 
188   auto ctx = CreateTraceProcessorContext();
189   AuxStreamManager manager(ctx.get());
190   ASSERT_TRUE(manager.OnAuxtraceInfoRecord(CreateAuxtraceInfoRecord()).ok());
191 
192   uint64_t aux_offset = 0;
193   uint64_t auxtrace_offset = 0;
194 
195   auto aux = [&](uint64_t size) {
196     manager.OnAuxRecord(CreateAuxRecord(aux_offset, size, kCpu));
197     aux_offset += size;
198   };
199   auto aux_hole = [&](uint64_t size) { aux_offset += size; };
200 
201   auto auxtrace = [&](uint64_t size) {
202     manager.OnAuxtraceRecord(CreateAuxtraceRecord(auxtrace_offset, size, kCpu),
203                              TraceBlobView(TraceBlob::Allocate(size)));
204     auxtrace_offset += size;
205   };
206   auto auxtrace_hole = [&](uint64_t size) { auxtrace_offset += size; };
207 
208   //          . . . . . . . . . . . . . . . . . . . . . .
209   //          |105                                      |
210   // Aux      |---|30         |10 |30         |-|20     |
211   // Auxtrace |5|10 |50                 |5|-|5|---|5|---|
212   // Result   |---|60                     |-|5|---|5|---|
213   //          . . . . . . . . . . . . . . . . . . . . . .
214   aux_hole(10);
215   aux(30);
216   aux(10);
217   aux(30);
218   aux_hole(5);
219   aux(20);
220   auxtrace(5);
221   auxtrace(10);
222   auxtrace(50);
223   auxtrace(5);
224   auxtrace_hole(5);
225   auxtrace(5);
226   auxtrace_hole(10);
227   auxtrace(5);
228 
229   manager.FinalizeStreams();
230 
231   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_missing].value, 15);
232   EXPECT_EQ(ctx->storage->stats()[stats::perf_auxtrace_missing].value, 25);
233   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 70);
234   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_lost].value, 35);
235 }
236 
TEST(AuxStreamManagerTest,StreamOverlapFails)237 TEST(AuxStreamManagerTest, StreamOverlapFails) {
238   constexpr uint64_t kSize = 10;
239   constexpr uint32_t kCpu = 0;
240   TraceBlobView data(TraceBlob::Allocate(kSize));
241   auto ctx = CreateTraceProcessorContext();
242   AuxStreamManager manager(ctx.get());
243   ASSERT_TRUE(manager.OnAuxtraceInfoRecord(CreateAuxtraceInfoRecord()).ok());
244 
245   EXPECT_TRUE(manager.OnAuxRecord(CreateAuxRecord(0, kSize, kCpu)).ok());
246   EXPECT_FALSE(manager.OnAuxRecord(CreateAuxRecord(0, kSize, kCpu)).ok());
247 
248   EXPECT_TRUE(
249       manager
250           .OnAuxtraceRecord(CreateAuxtraceRecord(0, kSize, kCpu), data.copy())
251           .ok());
252   EXPECT_FALSE(
253       manager
254           .OnAuxtraceRecord(CreateAuxtraceRecord(0, kSize, kCpu), data.copy())
255           .ok());
256 }
257 
TEST(AuxStreamManagerTest,MultipleStreams)258 TEST(AuxStreamManagerTest, MultipleStreams) {
259   constexpr uint64_t kSize = 10;
260   constexpr uint32_t kCpu_0 = 0;
261   constexpr uint32_t kCpu_1 = 1;
262   TraceBlobView data(TraceBlob::Allocate(kSize));
263   auto ctx = CreateTraceProcessorContext();
264   AuxStreamManager manager(ctx.get());
265   ASSERT_TRUE(manager.OnAuxtraceInfoRecord(CreateAuxtraceInfoRecord()).ok());
266 
267   EXPECT_TRUE(manager.OnAuxRecord(CreateAuxRecord(0, kSize, kCpu_0)).ok());
268   EXPECT_TRUE(manager.OnAuxRecord(CreateAuxRecord(0, kSize, kCpu_1)).ok());
269 
270   EXPECT_TRUE(
271       manager
272           .OnAuxtraceRecord(CreateAuxtraceRecord(0, kSize, kCpu_0), data.copy())
273           .ok());
274   EXPECT_TRUE(
275       manager
276           .OnAuxtraceRecord(CreateAuxtraceRecord(0, kSize, kCpu_1), data.copy())
277           .ok());
278 
279   manager.FinalizeStreams();
280 
281   EXPECT_EQ(ctx->storage->stats()[stats::perf_aux_ignored].value, 20);
282 }
283 
284 }  // namespace
285 }  // namespace perfetto::trace_processor::perf_importer
286