blob: 134bc9b983f957843b33f099b553b80c788753ea [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/tracing/perfetto/perfetto_service.h"
#include "services/tracing/perfetto/producer_host.h"
#include "services/tracing/perfetto/test_utils.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace tracing {
namespace {
const char kPerfettoTestDataSourceName[] =
"org.chromium.chrome_integration_unittest";
const char kPerfettoProducerName[] = "chrome_producer_test";
class PerfettoIntegrationTest : public testing::Test {
public:
void SetUp() override {
perfetto_service_ = std::make_unique<PerfettoService>();
RunUntilIdle();
ProducerClient::ResetTaskRunnerForTesting();
}
void TearDown() override { perfetto_service_.reset(); }
PerfettoService* perfetto_service() const { return perfetto_service_.get(); }
void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
private:
std::unique_ptr<PerfettoService> perfetto_service_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
};
TEST_F(PerfettoIntegrationTest, ProducerDatasourceInitialized) {
auto dummy_client =
std::make_unique<MockProducerClient>(0 /* send_packet_count */);
base::RunLoop producer_initialized_runloop;
auto new_producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), dummy_client.get(),
producer_initialized_runloop.QuitClosure());
producer_initialized_runloop.Run();
ProducerClient::DeleteSoonForTesting(std::move(dummy_client));
}
TEST_F(PerfettoIntegrationTest, ClientEnabledAndDisabled) {
base::RunLoop on_trace_packets;
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(),
[&on_trace_packets](bool has_more) {
EXPECT_FALSE(has_more);
on_trace_packets.Quit();
});
base::RunLoop client_enabled_callback;
base::RunLoop client_disabled_callback;
auto client = std::make_unique<MockProducerClient>(
0 /* send_packet_count */, client_enabled_callback.QuitClosure(),
client_disabled_callback.QuitClosure());
auto producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client.get());
client_enabled_callback.Run();
RunUntilIdle();
consumer.StopTracing();
client_disabled_callback.Run();
on_trace_packets.Run();
EXPECT_EQ(0u, consumer.received_packets());
ProducerClient::DeleteSoonForTesting(std::move(client));
}
TEST_F(PerfettoIntegrationTest, PacketsEndToEndProducerFirst) {
const size_t kNumPackets = 10;
base::RunLoop client_enabled_callback;
base::RunLoop client_disabled_callback;
auto client = std::make_unique<MockProducerClient>(
kNumPackets, client_enabled_callback.QuitClosure(),
client_disabled_callback.QuitClosure());
auto producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client.get());
base::RunLoop no_more_packets_runloop;
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(),
[&no_more_packets_runloop](bool has_more) {
if (!has_more) {
no_more_packets_runloop.Quit();
}
});
client_enabled_callback.Run();
RunUntilIdle();
consumer.StopTracing();
client_disabled_callback.Run();
no_more_packets_runloop.Run();
EXPECT_EQ(kNumPackets, consumer.received_packets());
ProducerClient::DeleteSoonForTesting(std::move(client));
}
TEST_F(PerfettoIntegrationTest, PacketsEndToEndConsumerFirst) {
const size_t kNumPackets = 10;
base::RunLoop no_more_packets_runloop;
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(),
[&no_more_packets_runloop](bool has_more) {
if (!has_more) {
no_more_packets_runloop.Quit();
}
});
base::RunLoop client_enabled_callback;
auto client = std::make_unique<MockProducerClient>(
kNumPackets, client_enabled_callback.QuitClosure());
auto new_producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client.get());
client_enabled_callback.Run();
RunUntilIdle();
consumer.StopTracing();
no_more_packets_runloop.Run();
EXPECT_EQ(kNumPackets, consumer.received_packets());
ProducerClient::DeleteSoonForTesting(std::move(client));
}
TEST_F(PerfettoIntegrationTest, CommitDataRequestIsMaybeComplete) {
const size_t kNumPackets = 100;
base::RunLoop no_more_packets_runloop;
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(),
[&no_more_packets_runloop](bool has_more) {
if (!has_more) {
no_more_packets_runloop.Quit();
}
});
base::RunLoop client_enabled_callback;
auto client = std::make_unique<MockProducerClient>(
kNumPackets, client_enabled_callback.QuitClosure());
auto new_producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client.get());
client_enabled_callback.Run();
base::RunLoop wait_for_packet_write;
client->GetTaskRunner()->GetOrCreateTaskRunner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&TestDataSource::WritePacketBigly,
base::Unretained(client->data_source())),
wait_for_packet_write.QuitClosure());
wait_for_packet_write.Run();
RunUntilIdle();
consumer.StopTracing();
no_more_packets_runloop.Run();
EXPECT_EQ(client->all_client_commit_data_requests(),
new_producer->all_host_commit_data_requests());
ProducerClient::DeleteSoonForTesting(std::move(client));
}
TEST_F(PerfettoIntegrationTest, TracingRestarted) {
const size_t kNumPackets = 10;
base::RunLoop no_more_packets_runloop;
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(),
[&no_more_packets_runloop](bool has_more) {
if (!has_more) {
no_more_packets_runloop.Quit();
}
});
base::RunLoop client_enabled_callback;
auto client = std::make_unique<MockProducerClient>(
kNumPackets, client_enabled_callback.QuitClosure());
auto new_producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client.get());
client_enabled_callback.Run();
RunUntilIdle();
perfetto::SharedMemory* first_session_shm = client->shared_memory();
consumer.StopTracing();
no_more_packets_runloop.Run();
EXPECT_EQ(kNumPackets, consumer.received_packets());
consumer.FreeBuffers();
base::RunLoop client_reenabled_callback;
client->SetAgentEnabledCallback(client_reenabled_callback.QuitClosure());
consumer.StartTracing();
client_reenabled_callback.Run();
RunUntilIdle();
// We should still be using the same shared memory.
EXPECT_EQ(first_session_shm, client->shared_memory());
base::RunLoop client_redisabled_callback;
client->SetAgentDisabledCallback(client_redisabled_callback.QuitClosure());
consumer.StopTracing();
client_redisabled_callback.Run();
EXPECT_EQ(kNumPackets * 2, consumer.received_packets());
ProducerClient::DeleteSoonForTesting(std::move(client));
}
TEST_F(PerfettoIntegrationTest, NoPacketsReceivedOnWrongSourceName) {
const size_t kNumPackets = 10;
base::RunLoop client_enabled_callback;
base::RunLoop client_disabled_callback;
auto client = std::make_unique<MockProducerClient>(
kNumPackets, client_enabled_callback.QuitClosure(),
client_disabled_callback.QuitClosure());
base::RunLoop producer_initialized_runloop;
auto new_producer = std::make_unique<MockProducerHost>(
kPerfettoProducerName, "fake_data_source",
perfetto_service()->GetService(), client.get());
base::RunLoop no_more_packets_runloop;
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(),
[&no_more_packets_runloop](bool has_more) {
if (!has_more) {
no_more_packets_runloop.Quit();
}
});
RunUntilIdle();
consumer.StopTracing();
no_more_packets_runloop.Run();
EXPECT_EQ(0u, consumer.received_packets());
ProducerClient::DeleteSoonForTesting(std::move(client));
}
TEST_F(PerfettoIntegrationTest,
DifferentSharedMemoryBuffersForDifferentAgents) {
base::RunLoop client1_enabled_callback;
base::RunLoop client2_enabled_callback;
auto client1 = std::make_unique<MockProducerClient>(
0 /* send_packet_count */, client1_enabled_callback.QuitClosure());
auto client2 = std::make_unique<MockProducerClient>(
0 /* send_packet_count */, client2_enabled_callback.QuitClosure());
auto producer1 = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client1.get());
auto producer2 = std::make_unique<MockProducerHost>(
kPerfettoProducerName, kPerfettoTestDataSourceName,
perfetto_service()->GetService(), client2.get());
MockConsumer consumer(kPerfettoTestDataSourceName,
perfetto_service()->GetService(), nullptr);
client1_enabled_callback.Run();
client2_enabled_callback.Run();
EXPECT_TRUE(client1->shared_memory());
EXPECT_TRUE(client2->shared_memory());
EXPECT_NE(client1->shared_memory(), client2->shared_memory());
ProducerClient::DeleteSoonForTesting(std::move(client1));
ProducerClient::DeleteSoonForTesting(std::move(client2));
}
} // namespace
} // namespace tracing