Create new TraceHelper for each tracing session.
This makes sure we do not accidentally keep old state.
Change-Id: Id9a18e76eea5dbc93c7623b5eeb5b9708612cd8c
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index dd063a7..9789d25 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -126,6 +126,13 @@
return pid;
}
+std::unique_ptr<TestHelper> GetHelper(base::TestTaskRunner* task_runner) {
+ std::unique_ptr<TestHelper> helper(new TestHelper(task_runner));
+ helper->ConnectConsumer();
+ helper->WaitForConsumerConnect();
+ return helper;
+}
+
class HeapprofdEndToEnd : public ::testing::Test {
public:
HeapprofdEndToEnd() {
@@ -134,27 +141,24 @@
// and then set to 1 again too quickly, init decides that the service is
// "restarting" and waits before restarting it.
usleep(50000);
- helper.StartServiceIfRequired();
unset_property = StartSystemHeapprofdIfRequired();
-
- helper.ConnectConsumer();
- helper.WaitForConsumerConnect();
}
protected:
base::TestTaskRunner task_runner;
- TestHelper helper{&task_runner};
void TraceAndValidate(const TraceConfig& trace_config,
pid_t pid,
uint64_t alloc_size) {
- helper.StartTracing(trace_config);
- helper.WaitForTracingDisabled(10000);
+ auto helper = GetHelper(&task_runner);
- helper.ReadData();
- helper.WaitForReadData();
+ helper->StartTracing(trace_config);
+ helper->WaitForTracingDisabled(10000);
- const auto& packets = helper.trace();
+ helper->ReadData();
+ helper->WaitForReadData();
+
+ const auto& packets = helper->trace();
ASSERT_GT(packets.size(), 0u);
size_t profile_packets = 0;
size_t samples = 0;
@@ -245,6 +249,8 @@
}
TEST_F(HeapprofdEndToEnd, NativeStartup) {
+ auto helper = GetHelper(&task_runner);
+
TraceConfig trace_config;
trace_config.add_buffers()->set_size_kb(10 * 1024);
trace_config.set_duration_ms(5000);
@@ -257,7 +263,7 @@
*heapprofd_config->add_process_cmdline() = "find";
heapprofd_config->set_all(false);
- helper.StartTracing(trace_config);
+ helper->StartTracing(trace_config);
// Wait to guarantee that the process forked below is hooked by the profiler
// by virtue of the startup check, and not by virtue of being seen as a
@@ -284,15 +290,15 @@
break;
}
- helper.WaitForTracingDisabled(10000);
+ helper->WaitForTracingDisabled(10000);
- helper.ReadData();
- helper.WaitForReadData();
+ helper->ReadData();
+ helper->WaitForReadData();
PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);
- const auto& packets = helper.trace();
+ const auto& packets = helper->trace();
ASSERT_GT(packets.size(), 0u);
size_t profile_packets = 0;
size_t samples = 0;
@@ -324,12 +330,8 @@
constexpr uint64_t kFirstIterationBytes = 5;
constexpr uint64_t kSecondIterationBytes = 7;
- base::Pipe signal_pipe = base::Pipe::Create();
- base::Pipe ack_pipe = base::Pipe::Create();
-
- ASSERT_EQ(fcntl(*signal_pipe.rd, F_SETFL,
- fcntl(*signal_pipe.rd, F_GETFL) | O_NONBLOCK),
- 0);
+ base::Pipe signal_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
+ base::Pipe ack_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
pid_t pid = fork();
switch (pid) {
@@ -348,7 +350,8 @@
free(const_cast<char*>(x));
}
char buf[1];
- if (read(*signal_pipe.rd, buf, sizeof(buf)) == sizeof(buf)) {
+ if (bool(signal_pipe.rd) &&
+ read(*signal_pipe.rd, buf, sizeof(buf)) == 0) {
bytes = kSecondIterationBytes;
signal_pipe.rd.reset();
ack_pipe.wr.reset();
@@ -365,7 +368,7 @@
TraceConfig trace_config;
trace_config.add_buffers()->set_size_kb(10 * 1024);
- trace_config.set_duration_ms(1000);
+ trace_config.set_duration_ms(2000);
auto* ds_config = trace_config.add_data_sources()->mutable_config();
ds_config->set_name("android.heapprofd");
@@ -375,17 +378,15 @@
heapprofd_config->set_sampling_interval_bytes(1);
*heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
heapprofd_config->set_all(false);
- heapprofd_config->mutable_continuous_dump_config()->set_dump_phase_ms(0);
- heapprofd_config->mutable_continuous_dump_config()->set_dump_interval_ms(100);
TraceAndValidate(trace_config, pid, kFirstIterationBytes);
- char buf[1] = {'1'};
- ASSERT_EQ(write(*signal_pipe.wr, buf, sizeof(buf)), sizeof(buf));
signal_pipe.wr.reset();
+ char buf[1];
ASSERT_EQ(read(*ack_pipe.rd, buf, sizeof(buf)), 0);
ack_pipe.rd.reset();
+ PERFETTO_LOG("HeapprofdEndToEnd::Reinit: Starting second");
TraceAndValidate(trace_config, pid, kSecondIterationBytes);
PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
diff --git a/test/test_helper.cc b/test/test_helper.cc
index afdd8eb..e019a5f 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -28,6 +28,8 @@
namespace perfetto {
+uint64_t TestHelper::next_instance_num_ = 0;
+
// If we're building on Android and starting the daemons ourselves,
// create the sockets in a world-writable location.
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
@@ -40,7 +42,8 @@
#endif
TestHelper::TestHelper(base::TestTaskRunner* task_runner)
- : task_runner_(task_runner),
+ : instance_num_(next_instance_num_++),
+ task_runner_(task_runner),
service_thread_("perfetto.svc"),
producer_thread_("perfetto.prd") {}
@@ -83,9 +86,8 @@
FakeProducer* TestHelper::ConnectFakeProducer() {
std::unique_ptr<FakeProducerDelegate> producer_delegate(
- new FakeProducerDelegate(
- TEST_PRODUCER_SOCK_NAME,
- WrapTask(task_runner_->CreateCheckpoint("producer.enabled"))));
+ new FakeProducerDelegate(TEST_PRODUCER_SOCK_NAME,
+ WrapTask(CreateCheckpoint("producer.enabled"))));
FakeProducerDelegate* producer_delegate_cached = producer_delegate.get();
producer_thread_.Start(std::move(producer_delegate));
return producer_delegate_cached->producer();
@@ -93,34 +95,35 @@
void TestHelper::ConnectConsumer() {
cur_consumer_num_++;
- on_connect_callback_ = task_runner_->CreateCheckpoint(
- "consumer.connected." + std::to_string(cur_consumer_num_));
+ on_connect_callback_ = CreateCheckpoint("consumer.connected." +
+ std::to_string(cur_consumer_num_));
endpoint_ =
ConsumerIPCClient::Connect(TEST_CONSUMER_SOCK_NAME, this, task_runner_);
}
void TestHelper::DetachConsumer(const std::string& key) {
- on_detach_callback_ = task_runner_->CreateCheckpoint("detach." + key);
+ on_detach_callback_ = CreateCheckpoint("detach." + key);
endpoint_->Detach(key);
- task_runner_->RunUntilCheckpoint("detach." + key);
+ RunUntilCheckpoint("detach." + key);
endpoint_.reset();
}
bool TestHelper::AttachConsumer(const std::string& key) {
bool success = false;
- auto checkpoint = task_runner_->CreateCheckpoint("attach." + key);
+ auto checkpoint = CreateCheckpoint("attach." + key);
on_attach_callback_ = [&success, checkpoint](bool s) {
success = s;
checkpoint();
};
endpoint_->Attach(key);
- task_runner_->RunUntilCheckpoint("attach." + key);
+ RunUntilCheckpoint("attach." + key);
return success;
}
void TestHelper::StartTracing(const TraceConfig& config,
base::ScopedFile file) {
- on_stop_tracing_callback_ = task_runner_->CreateCheckpoint("stop.tracing");
+ trace_.clear();
+ on_stop_tracing_callback_ = CreateCheckpoint("stop.tracing");
endpoint_->EnableTracing(config, std::move(file));
}
@@ -131,33 +134,31 @@
void TestHelper::FlushAndWait(uint32_t timeout_ms) {
static int flush_num = 0;
std::string checkpoint_name = "flush." + std::to_string(flush_num++);
- auto checkpoint = task_runner_->CreateCheckpoint(checkpoint_name);
+ auto checkpoint = CreateCheckpoint(checkpoint_name);
endpoint_->Flush(timeout_ms, [checkpoint](bool) { checkpoint(); });
- task_runner_->RunUntilCheckpoint(checkpoint_name, timeout_ms + 1000);
+ RunUntilCheckpoint(checkpoint_name, timeout_ms + 1000);
}
void TestHelper::ReadData(uint32_t read_count) {
- on_packets_finished_callback_ = task_runner_->CreateCheckpoint(
- "readback.complete." + std::to_string(read_count));
+ on_packets_finished_callback_ =
+ CreateCheckpoint("readback.complete." + std::to_string(read_count));
endpoint_->ReadBuffers();
}
void TestHelper::WaitForConsumerConnect() {
- task_runner_->RunUntilCheckpoint("consumer.connected." +
- std::to_string(cur_consumer_num_));
+ RunUntilCheckpoint("consumer.connected." + std::to_string(cur_consumer_num_));
}
void TestHelper::WaitForProducerEnabled() {
- task_runner_->RunUntilCheckpoint("producer.enabled");
+ RunUntilCheckpoint("producer.enabled");
}
void TestHelper::WaitForTracingDisabled(uint32_t timeout_ms) {
- task_runner_->RunUntilCheckpoint("stop.tracing", timeout_ms);
+ RunUntilCheckpoint("stop.tracing", timeout_ms);
}
void TestHelper::WaitForReadData(uint32_t read_count) {
- task_runner_->RunUntilCheckpoint("readback.complete." +
- std::to_string(read_count));
+ RunUntilCheckpoint("readback.complete." + std::to_string(read_count));
}
std::function<void()> TestHelper::WrapTask(
diff --git a/test/test_helper.h b/test/test_helper.h
index f2fe7dd..21caa66 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -61,6 +61,19 @@
void WaitForTracingDisabled(uint32_t timeout_ms = 5000);
void WaitForReadData(uint32_t read_count = 0);
+ std::string AddID(const std::string& checkpoint) {
+ return checkpoint + "." + std::to_string(instance_num_);
+ }
+
+ std::function<void()> CreateCheckpoint(const std::string& checkpoint) {
+ return task_runner_->CreateCheckpoint(AddID(checkpoint));
+ }
+
+ void RunUntilCheckpoint(const std::string& checkpoint,
+ uint32_t timeout_ms = 5000) {
+ return task_runner_->RunUntilCheckpoint(AddID(checkpoint), timeout_ms);
+ }
+
std::function<void()> WrapTask(const std::function<void()>& function);
TaskRunnerThread* service_thread() { return &service_thread_; }
@@ -68,6 +81,8 @@
const std::vector<protos::TracePacket>& trace() { return trace_; }
private:
+ static uint64_t next_instance_num_;
+ uint64_t instance_num_;
base::TestTaskRunner* task_runner_ = nullptr;
int cur_consumer_num_ = 0;