#include "src/tracing/service/tracing_service_impl.h"
#include <atomic>
#include <cinttypes>
#include <cstdint>
#include <cstring>
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/proc_utils.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/pipe.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/sys_types.h"
#include "perfetto/ext/base/temp_file.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/base/uuid.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/client_identity.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/producer.h"
#include "perfetto/ext/tracing/core/shared_memory.h"
#include "perfetto/ext/tracing/core/shared_memory_abi.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
#include "perfetto/ext/tracing/core/tracing_service.h"
#include "perfetto/protozero/contiguous_memory_range.h"
#include "perfetto/protozero/message_arena.h"
#include "perfetto/protozero/scattered_stream_writer.h"
#include "perfetto/tracing/buffer_exhausted_policy.h"
#include "perfetto/tracing/core/flush_flags.h"
#include "perfetto/tracing/core/forward_decls.h"
#include "protos/perfetto/common/builtin_clock.gen.h"
#include "protos/perfetto/trace/clock_snapshot.gen.h"
#include "protos/perfetto/trace/remote_clock_sync.gen.h"
#include "src/base/test/test_task_runner.h"
#include "src/protozero/filtering/filter_bytecode_generator.h"
#include "src/tracing/core/shared_memory_arbiter_impl.h"
#include "src/tracing/core/trace_writer_impl.h"
#include "src/tracing/test/mock_consumer.h"
#include "src/tracing/test/mock_producer.h"
#include "src/tracing/test/test_shared_memory.h"
#include "test/gtest_and_gmock.h"
#include "protos/perfetto/common/track_event_descriptor.gen.h"
#include "protos/perfetto/trace/perfetto/tracing_service_event.gen.h"
#include "protos/perfetto/trace/test_event.gen.h"
#include "protos/perfetto/trace/test_event.pbzero.h"
#include "protos/perfetto/trace/trace.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "protos/perfetto/trace/trace_uuid.gen.h"
#include "protos/perfetto/trace/trigger.gen.h"
#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
#include <zlib.h>
#include "src/tracing/service/zlib_compressor.h"
#endif
_;
AssertionFailure;
AssertionResult;
AssertionSuccess;
Contains;
ContainsRegex;
DoAll;
Each;
ElementsAre;
ElementsAreArray;
Eq;
ExplainMatchResult;
HasSubstr;
InSequence;
Invoke;
InvokeWithoutArgs;
IsEmpty;
Mock;
Ne;
Not;
Pointee;
Property;
Return;
SaveArg;
StrictMock;
StringMatchResultListener;
StrNe;
UnorderedElementsAre;
namespace perfetto {
namespace {
constexpr size_t kDefaultShmSizeKb = …;
constexpr size_t kDefaultShmPageSizeKb = …;
constexpr size_t kMaxShmSizeKb = …;
AssertionResult HasTriggerModeInternal(
const std::vector<protos::gen::TracePacket>& packets,
protos::gen::TraceConfig::TriggerConfig::TriggerMode mode) { … }
MATCHER_P(HasTriggerMode, mode, "") { … }
MATCHER_P(LowerCase,
m,
"Lower case " + testing::DescribeMatcher<std::string>(m, negation)) { … }
#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
std::string Decompress(const std::string& data) { … }
std::vector<protos::gen::TracePacket> DecompressTrace(
const std::vector<protos::gen::TracePacket> compressed) { … }
#endif
}
class TracingServiceImplTest : public testing::Test { … };
TEST_F(TracingServiceImplTest, AtMostOneConfig) { … }
TEST_F(TracingServiceImplTest, CantBackToBackConfigsForWithExtraGuardrails) { … }
TEST_F(TracingServiceImplTest, RegisterAndUnregister) { … }
TEST_F(TracingServiceImplTest, EnableAndDisableTracing) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerDeferredStart) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerTimeOut) { … }
TEST_F(TracingServiceImplTest, FailOnUnknownTrigger) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerDifferentProducer) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerCorrectProducer) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerDifferentTrigger) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerMultipleTriggers) { … }
TEST_F(TracingServiceImplTest, StartTracingTriggerMultipleTraces) { … }
TEST_F(TracingServiceImplTest, EmitTriggersWithStartTracingTrigger) { … }
TEST_F(TracingServiceImplTest, EmitTriggersWithStopTracingTrigger) { … }
TEST_F(TracingServiceImplTest, EmitTriggersRepeatedly) { … }
TEST_F(TracingServiceImplTest, StopTracingTriggerTimeout) { … }
TEST_F(TracingServiceImplTest, StopTracingTriggerRingBuffer) { … }
TEST_F(TracingServiceImplTest, StopTracingTriggerMultipleTriggers) { … }
TEST_F(TracingServiceImplTest, SecondTriggerHitsLimit) { … }
TEST_F(TracingServiceImplTest, SecondTriggerDoesntHitLimit) { … }
TEST_F(TracingServiceImplTest, SkipProbability) { … }
TEST_F(TracingServiceImplTest, CloneSnapshotTriggers) { … }
TEST_F(TracingServiceImplTest, LockdownMode) { … }
TEST_F(TracingServiceImplTest, ProducerNameFilterChange) { … }
TEST_F(TracingServiceImplTest, ProducerNameFilterChangeTwoDataSources) { … }
TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) { … }
TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) { … }
TEST_F(TracingServiceImplTest, ProducerIDWrapping) { … }
TEST_F(TracingServiceImplTest, CompressionConfiguredButUnsupported) { … }
#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
TEST_F(TracingServiceImplTest, CompressionReadIpc) { … }
TEST_F(TracingServiceImplTest, CompressionWriteIntoFile) { … }
TEST_F(TracingServiceImplTest, CloneSessionWithCompression) { … }
#endif
TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) { … }
TEST_F(TracingServiceImplTest, WriteIntoFileWithPath) { … }
TEST_F(TracingServiceImplTest, WriteIntoFileFilterMultipleChunks) { … }
TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) { … }
TEST_F(TracingServiceImplTest, ExplicitFlush) { … }
TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) { … }
TEST_F(TracingServiceImplTest, BatchFlushes) { … }
TEST_F(TracingServiceImplTest, PeriodicFlush) { … }
TEST_F(TracingServiceImplTest, NoFlush) { … }
TEST_F(TracingServiceImplTest, PeriodicClearIncrementalState) { … }
TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) { … }
TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) { … }
TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) { … }
TEST_F(TracingServiceImplTest, SessionId) { … }
TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) { … }
TEST_F(TracingServiceImplTest, DeferredStart) { … }
TEST_F(TracingServiceImplTest, ProducerUIDsAndPacketSequenceIDs) { … }
TEST_F(TracingServiceImplTest, AllowedBuffers) { … }
#if !PERFETTO_DCHECK_IS_ON()
TEST_F(TracingServiceImplTest, CommitToForbiddenBufferIsDiscarded) {
std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
consumer->Connect(svc.get());
std::unique_ptr<MockProducer> producer = CreateMockProducer();
producer->Connect(svc.get(), "mock_producer");
ProducerID producer_id = *last_producer_id();
producer->RegisterDataSource("data_source");
EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
TraceConfig trace_config;
trace_config.add_buffers()->set_size_kb(128);
trace_config.add_buffers()->set_size_kb(128);
auto* ds_config = trace_config.add_data_sources()->mutable_config();
ds_config->set_name("data_source");
ds_config->set_target_buffer(0);
consumer->EnableTracing(trace_config);
ASSERT_EQ(2u, tracing_session()->num_buffers());
std::set<BufferID> expected_buffers = {tracing_session()->buffers_index[0]};
EXPECT_EQ(expected_buffers, GetAllowedTargetBuffers(producer_id));
producer->WaitForTracingSetup();
producer->WaitForDataSourceSetup("data_source");
producer->WaitForDataSourceStart("data_source");
std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
tracing_session()->buffers_index[0]);
{
auto tp = writer->NewTracePacket();
tp->set_for_testing()->set_str("good_payload");
}
auto flush_request = consumer->Flush();
producer->ExpectFlush(writer.get());
ASSERT_TRUE(flush_request.WaitForReply());
writer = producer->endpoint()->CreateTraceWriter(
tracing_session()->buffers_index[1]);
{
auto tp = writer->NewTracePacket();
tp->set_for_testing()->set_str("bad_payload");
}
flush_request = consumer->Flush();
producer->ExpectFlush(writer.get());
ASSERT_TRUE(flush_request.WaitForReply());
consumer->DisableTracing();
producer->WaitForDataSourceStop("data_source");
consumer->WaitForTracingDisabled();
auto packets = consumer->ReadBuffers();
EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
Property(&protos::gen::TestEvent::str,
Eq("good_payload")))));
EXPECT_THAT(packets,
Not(Contains(Property(
&protos::gen::TracePacket::for_testing,
Property(&protos::gen::TestEvent::str, Eq("bad_payload"))))));
consumer->FreeBuffers();
EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
}
#endif
TEST_F(TracingServiceImplTest, RegisterAndUnregisterTraceWriter) { … }
TEST_F(TracingServiceImplTest, ScrapeBuffersOnFlush) { … }
TEST_F(TracingServiceImplTest, ScrapeBuffersFromAnotherThread) { … }
TEST_F(TracingServiceImplTest, ScrapeBuffersOnProducerDisconnect) { … }
TEST_F(TracingServiceImplTest, ScrapeBuffersOnDisable) { … }
class TracingServiceImplScrapingWithSmbTest : public TracingServiceImplTest { … };
TEST_F(TracingServiceImplScrapingWithSmbTest, ScrapeAfterInflatedCount) { … }
TEST_F(TracingServiceImplScrapingWithSmbTest, ScrapeAfterCompleteChunk) { … }
TEST_F(TracingServiceImplTest, AbortIfTraceDurationIsTooLong) { … }
TEST_F(TracingServiceImplTest, GetTraceStats) { … }
TEST_F(TracingServiceImplTest, TraceWriterStats) { … }
TEST_F(TracingServiceImplTest, ObserveEventsDataSourceInstances) { … }
TEST_F(TracingServiceImplTest, ObserveEventsDataSourceInstancesUnregister) { … }
TEST_F(TracingServiceImplTest, ObserveAllDataSourceStarted) { … }
TEST_F(TracingServiceImplTest,
ObserveAllDataSourceStartedWithoutMatchingInstances) { … }
TEST_F(TracingServiceImplTest, ObserveAllDataSourceStartedOnlySomeWillAck) { … }
TEST_F(TracingServiceImplTest, ObserveAllDataSourceStartedNoAck) { … }
TEST_F(TracingServiceImplTest, LifecycleEventSmoke) { … }
TEST_F(TracingServiceImplTest, LifecycleMultipleFlushEventsQueued) { … }
TEST_F(TracingServiceImplTest, QueryServiceState) { … }
TEST_F(TracingServiceImplTest, UpdateDataSource) { … }
TEST_F(TracingServiceImplTest, LimitSessionsPerUid) { … }
TEST_F(TracingServiceImplTest, ProducerProvidedSMB) { … }
TEST_F(TracingServiceImplTest, ProducerProvidedSMBInvalidSizes) { … }
TEST_F(TracingServiceImplTest, UuidPacketMatchesConfigUuid) { … }
TEST_F(TracingServiceImplTest, RandomUuidIfNoConfigUuid) { … }
TEST_F(TracingServiceImplTest, CloneSession) { … }
TEST_F(TracingServiceImplTest, CloneSessionAcrossUidDenied) { … }
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
TEST_F(TracingServiceImplTest, CloneSessionAcrossUidForBugreport) {
std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
consumer->Connect(svc.get());
std::unique_ptr<MockProducer> producer = CreateMockProducer();
producer->Connect(svc.get(), "mock_producer");
producer->RegisterDataSource("ds_1");
std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
clone_consumer->Connect(svc.get(), AID_SHELL);
TraceConfig trace_config;
trace_config.add_buffers()->set_size_kb(32);
trace_config.set_bugreport_score(1);
trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
protozero::FilterBytecodeGenerator filt;
filt.AddNestedField(1 , 1);
filt.EndMessage();
filt.AddSimpleField(protos::pbzero::TracePacket::kTraceUuidFieldNumber);
filt.EndMessage();
trace_config.mutable_trace_filter()->set_bytecode_v2(filt.Serialize());
consumer->EnableTracing(trace_config);
producer->WaitForTracingSetup();
producer->WaitForDataSourceSetup("ds_1");
producer->WaitForDataSourceStart("ds_1");
std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
writer->NewTracePacket()->set_for_testing()->set_str("payload");
writer.reset();
auto flush_request = consumer->Flush();
FlushFlags flush_flags(FlushFlags::Initiator::kConsumerSdk,
FlushFlags::Reason::kExplicit);
producer->ExpectFlush({}, true, flush_flags);
ASSERT_TRUE(flush_request.WaitForReply());
auto clone_done = task_runner.CreateCheckpoint("clone_done");
EXPECT_CALL(*clone_consumer, OnSessionCloned(_))
.WillOnce(Invoke([clone_done](const Consumer::OnSessionClonedArgs& args) {
clone_done();
ASSERT_TRUE(args.success);
}));
FlushFlags flush_flags2(FlushFlags::Initiator::kTraced,
FlushFlags::Reason::kTraceClone,
FlushFlags::CloneTarget::kBugreport);
producer->ExpectFlush({}, true, flush_flags2);
clone_consumer->CloneSession(kBugreportSessionId);
task_runner.RunUntilCheckpoint("clone_done");
auto packets = clone_consumer->ReadBuffers();
EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
Property(&protos::gen::TestEvent::str,
HasSubstr("payload")))));
}
#endif
TEST_F(TracingServiceImplTest, TransferOnClone) { … }
TEST_F(TracingServiceImplTest, ClearBeforeClone) { … }
TEST_F(TracingServiceImplTest, CloneMainSessionStopped) { … }
TEST_F(TracingServiceImplTest, CloneConsumerDisconnect) { … }
TEST_F(TracingServiceImplTest, CloneMainSessionGoesAwayDuringFlush) { … }
TEST_F(TracingServiceImplTest, CloneTransferFlush) { … }
TEST_F(TracingServiceImplTest, InvalidBufferSizes) { … }
TEST_F(TracingServiceImplTest, StringFiltering) { … }
TEST_F(TracingServiceImplTest, StringFilteringAndCloneSession) { … }
TEST_F(TracingServiceImplTest, ConsumerDisconnectionRacesFlushAndDisable) { … }
TEST_F(TracingServiceImplTest, RelayEndpointClockSync) { … }
TEST_F(TracingServiceImplTest, RelayEndpointDisconnect) { … }
TEST_F(TracingServiceImplTest, SessionSemaphoreMutexSingleSession) { … }
TEST_F(TracingServiceImplTest, SessionSemaphoreMutexMultipleSession) { … }
TEST_F(TracingServiceImplTest, SessionSemaphoreHigherCurrentFails) { … }
TEST_F(TracingServiceImplTest, SessionSemaphoreHigherPreviousFails) { … }
TEST_F(TracingServiceImplTest, SessionSemaphoreAllowedUpToLimit) { … }
TEST_F(TracingServiceImplTest, DetachAttach) { … }
TEST_F(TracingServiceImplTest, DetachDurationTimeoutFreeBuffers) { … }
}