blob: a8657d28be201144c06409bdba4798312d1f05cb [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/trace_processor/sorter/trace_token_buffer.h"
#include <optional>
#include "perfetto/base/compiler.h"
#include "perfetto/trace_processor/trace_blob.h"
#include "perfetto/trace_processor/trace_blob_view.h"
#include "src/trace_processor/importers/common/parser_types.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
namespace {
class TraceTokenBufferUnittest : public testing::Test {
protected:
TraceTokenBuffer store;
TraceProcessorContext context;
PacketSequenceState state{&context};
};
TEST_F(TraceTokenBufferUnittest, TracePacketDataInOut) {
TraceBlobView tbv(TraceBlob::Allocate(1024));
TracePacketData tpd{tbv.copy(), state.current_generation()};
TraceTokenBuffer::Id id = store.Append(std::move(tpd));
TracePacketData extracted = store.Extract<TracePacketData>(id);
ASSERT_EQ(extracted.packet, tbv);
ASSERT_EQ(extracted.sequence_state, state.current_generation());
}
TEST_F(TraceTokenBufferUnittest, PacketAppendMultipleBlobs) {
TraceBlobView tbv_1(TraceBlob::Allocate(1024));
TraceBlobView tbv_2(TraceBlob::Allocate(2048));
TraceBlobView tbv_3(TraceBlob::Allocate(4096));
TraceTokenBuffer::Id id_1 =
store.Append(TracePacketData{tbv_1.copy(), state.current_generation()});
TraceTokenBuffer::Id id_2 =
store.Append(TracePacketData{tbv_2.copy(), state.current_generation()});
ASSERT_EQ(store.Extract<TracePacketData>(id_1).packet, tbv_1);
ASSERT_EQ(store.Extract<TracePacketData>(id_2).packet, tbv_2);
TraceTokenBuffer::Id id_3 =
store.Append(TracePacketData{tbv_3.copy(), state.current_generation()});
ASSERT_EQ(store.Extract<TracePacketData>(id_3).packet, tbv_3);
}
TEST_F(TraceTokenBufferUnittest, BlobSharing) {
TraceBlobView root(TraceBlob::Allocate(2048));
TraceBlobView tbv_1 = root.slice_off(0, 1024);
TraceBlobView tbv_2 = root.slice_off(1024, 512);
TraceBlobView tbv_3 = root.slice_off(1536, 512);
TraceTokenBuffer::Id id_1 =
store.Append(TracePacketData{tbv_1.copy(), state.current_generation()});
TraceTokenBuffer::Id id_2 =
store.Append(TracePacketData{tbv_2.copy(), state.current_generation()});
ASSERT_EQ(store.Extract<TracePacketData>(id_1).packet, tbv_1);
ASSERT_EQ(store.Extract<TracePacketData>(id_2).packet, tbv_2);
TraceTokenBuffer::Id id_3 =
store.Append(TracePacketData{tbv_3.copy(), state.current_generation()});
ASSERT_EQ(store.Extract<TracePacketData>(id_3).packet, tbv_3);
}
TEST_F(TraceTokenBufferUnittest, SequenceStateSharing) {
TraceBlobView root(TraceBlob::Allocate(2048));
TraceBlobView tbv_1 = root.slice_off(0, 1024);
TraceBlobView tbv_2 = root.slice_off(1024, 512);
TraceTokenBuffer::Id id_1 =
store.Append(TracePacketData{tbv_1.copy(), state.current_generation()});
TraceTokenBuffer::Id id_2 =
store.Append(TracePacketData{tbv_2.copy(), state.current_generation()});
ASSERT_EQ(store.Extract<TracePacketData>(id_1).sequence_state,
state.current_generation());
ASSERT_EQ(store.Extract<TracePacketData>(id_2).sequence_state,
state.current_generation());
}
TEST_F(TraceTokenBufferUnittest, ManySequenceState) {
TraceBlobView root(TraceBlob::Allocate(1024));
std::array<TraceTokenBuffer::Id, 1024> ids;
std::array<PacketSequenceStateGeneration*, 1024> refs;
for (uint32_t i = 0; i < 1024; ++i) {
refs[i] = state.current_generation().get();
ids[i] = store.Append(
TracePacketData{root.slice_off(i, 1), state.current_generation()});
state.OnIncrementalStateCleared();
}
for (uint32_t i = 0; i < 1024; ++i) {
ASSERT_EQ(refs[i],
store.Extract<TracePacketData>(ids[i]).sequence_state.get());
}
}
TEST_F(TraceTokenBufferUnittest, PacketLargeOffset) {
TraceBlobView tbv(TraceBlob::Allocate(256ul * 1024));
TraceBlobView slice_1 = tbv.slice_off(0, 1024ul);
TraceTokenBuffer::Id id_1 =
store.Append(TracePacketData{slice_1.copy(), state.current_generation()});
TracePacketData out_1 = store.Extract<TracePacketData>(id_1);
ASSERT_EQ(out_1.packet, slice_1);
ASSERT_EQ(out_1.sequence_state, state.current_generation());
TraceBlobView slice_2 = tbv.slice_off(128ul * 1024, 1024ul);
TraceTokenBuffer::Id id_2 =
store.Append(TracePacketData{slice_2.copy(), state.current_generation()});
TracePacketData out_2 = store.Extract<TracePacketData>(id_2);
ASSERT_EQ(out_2.packet, slice_2);
ASSERT_EQ(out_2.sequence_state, state.current_generation());
}
TEST_F(TraceTokenBufferUnittest, TrackEventDataInOut) {
TraceBlobView tbv(TraceBlob::Allocate(1234));
TrackEventData ted(tbv.copy(), state.current_generation());
ted.thread_instruction_count = 123;
ted.extra_counter_values = {10, 2, 0, 0, 0, 0, 0, 0};
auto counter_array = ted.extra_counter_values;
TraceTokenBuffer::Id id = store.Append(std::move(ted));
TrackEventData extracted = store.Extract<TrackEventData>(id);
ASSERT_EQ(extracted.trace_packet_data.packet, tbv);
ASSERT_EQ(extracted.trace_packet_data.sequence_state,
state.current_generation());
ASSERT_EQ(extracted.thread_instruction_count, 123);
ASSERT_EQ(extracted.thread_timestamp, std::nullopt);
ASSERT_DOUBLE_EQ(extracted.counter_value, 0.0);
ASSERT_EQ(extracted.extra_counter_values, counter_array);
}
TEST_F(TraceTokenBufferUnittest, ExtractOrAppendAfterFreeMemory) {
auto unused_res = store.Extract<TraceBlobView>(
store.Append(TraceBlobView(TraceBlob::Allocate(1234))));
base::ignore_result(unused_res);
store.FreeMemory();
TraceTokenBuffer::Id id =
store.Append(TraceBlobView(TraceBlob::Allocate(4567)));
TraceBlobView tbv = store.Extract<TraceBlobView>(id);
ASSERT_EQ(tbv.size(), 4567u);
}
} // namespace
} // namespace trace_processor
} // namespace perfetto