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/sorter/trace_token_buffer.h"
18
19 #include <optional>
20
21 #include "perfetto/base/compiler.h"
22 #include "perfetto/trace_processor/ref_counted.h"
23 #include "perfetto/trace_processor/trace_blob.h"
24 #include "perfetto/trace_processor/trace_blob_view.h"
25 #include "src/trace_processor/importers/common/parser_types.h"
26 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
27 #include "src/trace_processor/types/trace_processor_context.h"
28 #include "test/gtest_and_gmock.h"
29
30 namespace perfetto {
31 namespace trace_processor {
32 namespace {
33
34 class TraceTokenBufferUnittest : public testing::Test {
35 protected:
36 TraceTokenBuffer store;
37 TraceProcessorContext context;
38 RefPtr<PacketSequenceStateGeneration> state =
39 PacketSequenceStateGeneration::CreateFirst(&context);
40 };
41
TEST_F(TraceTokenBufferUnittest,TracePacketDataInOut)42 TEST_F(TraceTokenBufferUnittest, TracePacketDataInOut) {
43 TraceBlobView tbv(TraceBlob::Allocate(1024));
44 TracePacketData tpd{tbv.copy(), state};
45
46 TraceTokenBuffer::Id id = store.Append(std::move(tpd));
47 TracePacketData extracted = store.Extract<TracePacketData>(id);
48 ASSERT_EQ(extracted.packet, tbv);
49 ASSERT_EQ(extracted.sequence_state, state);
50 }
51
TEST_F(TraceTokenBufferUnittest,PacketAppendMultipleBlobs)52 TEST_F(TraceTokenBufferUnittest, PacketAppendMultipleBlobs) {
53 TraceBlobView tbv_1(TraceBlob::Allocate(1024));
54 TraceBlobView tbv_2(TraceBlob::Allocate(2048));
55 TraceBlobView tbv_3(TraceBlob::Allocate(4096));
56
57 TraceTokenBuffer::Id id_1 =
58 store.Append(TracePacketData{tbv_1.copy(), state});
59 TraceTokenBuffer::Id id_2 =
60 store.Append(TracePacketData{tbv_2.copy(), state});
61 ASSERT_EQ(store.Extract<TracePacketData>(id_1).packet, tbv_1);
62 ASSERT_EQ(store.Extract<TracePacketData>(id_2).packet, tbv_2);
63
64 TraceTokenBuffer::Id id_3 =
65 store.Append(TracePacketData{tbv_3.copy(), state});
66 ASSERT_EQ(store.Extract<TracePacketData>(id_3).packet, tbv_3);
67 }
68
TEST_F(TraceTokenBufferUnittest,BlobSharing)69 TEST_F(TraceTokenBufferUnittest, BlobSharing) {
70 TraceBlobView root(TraceBlob::Allocate(2048));
71 TraceBlobView tbv_1 = root.slice_off(0, 1024);
72 TraceBlobView tbv_2 = root.slice_off(1024, 512);
73 TraceBlobView tbv_3 = root.slice_off(1536, 512);
74
75 TraceTokenBuffer::Id id_1 =
76 store.Append(TracePacketData{tbv_1.copy(), state});
77 TraceTokenBuffer::Id id_2 =
78 store.Append(TracePacketData{tbv_2.copy(), state});
79 ASSERT_EQ(store.Extract<TracePacketData>(id_1).packet, tbv_1);
80 ASSERT_EQ(store.Extract<TracePacketData>(id_2).packet, tbv_2);
81
82 TraceTokenBuffer::Id id_3 =
83 store.Append(TracePacketData{tbv_3.copy(), state});
84 ASSERT_EQ(store.Extract<TracePacketData>(id_3).packet, tbv_3);
85 }
86
TEST_F(TraceTokenBufferUnittest,SequenceStateSharing)87 TEST_F(TraceTokenBufferUnittest, SequenceStateSharing) {
88 TraceBlobView root(TraceBlob::Allocate(2048));
89 TraceBlobView tbv_1 = root.slice_off(0, 1024);
90 TraceBlobView tbv_2 = root.slice_off(1024, 512);
91
92 TraceTokenBuffer::Id id_1 =
93 store.Append(TracePacketData{tbv_1.copy(), state});
94 TraceTokenBuffer::Id id_2 =
95 store.Append(TracePacketData{tbv_2.copy(), state});
96 ASSERT_EQ(store.Extract<TracePacketData>(id_1).sequence_state, state);
97 ASSERT_EQ(store.Extract<TracePacketData>(id_2).sequence_state, state);
98 }
99
TEST_F(TraceTokenBufferUnittest,ManySequenceState)100 TEST_F(TraceTokenBufferUnittest, ManySequenceState) {
101 TraceBlobView root(TraceBlob::Allocate(1024));
102
103 std::array<TraceTokenBuffer::Id, 1024> ids;
104 std::array<PacketSequenceStateGeneration*, 1024> refs;
105 for (uint32_t i = 0; i < 1024; ++i) {
106 refs[i] = state.get();
107 ids[i] = store.Append(TracePacketData{root.slice_off(i, 1), state});
108 state = state->OnNewTracePacketDefaults(TraceBlobView());
109 }
110
111 for (uint32_t i = 0; i < 1024; ++i) {
112 ASSERT_EQ(refs[i],
113 store.Extract<TracePacketData>(ids[i]).sequence_state.get());
114 }
115 }
116
TEST_F(TraceTokenBufferUnittest,PacketLargeOffset)117 TEST_F(TraceTokenBufferUnittest, PacketLargeOffset) {
118 TraceBlobView tbv(TraceBlob::Allocate(256ul * 1024));
119
120 TraceBlobView slice_1 = tbv.slice_off(0, 1024ul);
121 TraceTokenBuffer::Id id_1 =
122 store.Append(TracePacketData{slice_1.copy(), state});
123 TracePacketData out_1 = store.Extract<TracePacketData>(id_1);
124 ASSERT_EQ(out_1.packet, slice_1);
125 ASSERT_EQ(out_1.sequence_state, state);
126
127 TraceBlobView slice_2 = tbv.slice_off(128ul * 1024, 1024ul);
128 TraceTokenBuffer::Id id_2 =
129 store.Append(TracePacketData{slice_2.copy(), state});
130 TracePacketData out_2 = store.Extract<TracePacketData>(id_2);
131 ASSERT_EQ(out_2.packet, slice_2);
132 ASSERT_EQ(out_2.sequence_state, state);
133 }
134
TEST_F(TraceTokenBufferUnittest,TrackEventDataInOut)135 TEST_F(TraceTokenBufferUnittest, TrackEventDataInOut) {
136 TraceBlobView tbv(TraceBlob::Allocate(1234));
137 TrackEventData ted(tbv.copy(), state);
138 ted.thread_instruction_count = 123;
139 ted.extra_counter_values = {10, 2, 0, 0, 0, 0, 0, 0};
140 auto counter_array = ted.extra_counter_values;
141
142 TraceTokenBuffer::Id id = store.Append(std::move(ted));
143 TrackEventData extracted = store.Extract<TrackEventData>(id);
144 ASSERT_EQ(extracted.trace_packet_data.packet, tbv);
145 ASSERT_EQ(extracted.trace_packet_data.sequence_state, state);
146 ASSERT_EQ(extracted.thread_instruction_count, 123);
147 ASSERT_EQ(extracted.thread_timestamp, std::nullopt);
148 ASSERT_DOUBLE_EQ(extracted.counter_value, 0.0);
149 ASSERT_EQ(extracted.extra_counter_values, counter_array);
150 }
151
TEST_F(TraceTokenBufferUnittest,ExtractOrAppendAfterFreeMemory)152 TEST_F(TraceTokenBufferUnittest, ExtractOrAppendAfterFreeMemory) {
153 auto unused_res = store.Extract<TraceBlobView>(
154 store.Append(TraceBlobView(TraceBlob::Allocate(1234))));
155 base::ignore_result(unused_res);
156
157 store.FreeMemory();
158
159 TraceTokenBuffer::Id id =
160 store.Append(TraceBlobView(TraceBlob::Allocate(4567)));
161 TraceBlobView tbv = store.Extract<TraceBlobView>(id);
162 ASSERT_EQ(tbv.size(), 4567u);
163 }
164
165 } // namespace
166 } // namespace trace_processor
167 } // namespace perfetto
168