Merge "Simplify PERFETTO_EXPORT_COMPONENT"
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index a4c7777..51deba3 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -319,6 +319,7 @@
"../../base",
"../../base:test_support",
"../../tracing/core",
+ "../../tracing/test:test_support",
"../common:proc_utils",
"../common:unwind_support",
]
diff --git a/src/profiling/memory/heapprofd_producer_unittest.cc b/src/profiling/memory/heapprofd_producer_unittest.cc
index 78ed9ea..44dd606 100644
--- a/src/profiling/memory/heapprofd_producer_unittest.cc
+++ b/src/profiling/memory/heapprofd_producer_unittest.cc
@@ -22,6 +22,7 @@
#include "perfetto/ext/tracing/core/commit_data_request.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "src/base/test/test_task_runner.h"
+#include "src/tracing/test/mock_producer_endpoint.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
@@ -32,29 +33,6 @@
using ::testing::Pair;
using ::testing::Property;
-class MockProducerEndpoint : public TracingService::ProducerEndpoint {
- public:
- MOCK_METHOD1(UnregisterDataSource, void(const std::string&));
- MOCK_METHOD1(NotifyFlushComplete, void(FlushRequestID));
- MOCK_METHOD1(NotifyDataSourceStarted, void(DataSourceInstanceID));
- MOCK_METHOD1(NotifyDataSourceStopped, void(DataSourceInstanceID));
-
- MOCK_CONST_METHOD0(shared_memory, SharedMemory*());
- MOCK_CONST_METHOD0(shared_buffer_page_size_kb, size_t());
- MOCK_METHOD2(CreateTraceWriter,
- std::unique_ptr<TraceWriter>(BufferID, BufferExhaustedPolicy));
- MOCK_METHOD0(MaybeSharedMemoryArbiter, SharedMemoryArbiter*());
- MOCK_CONST_METHOD0(IsShmemProvidedByProducer, bool());
- MOCK_METHOD1(ActivateTriggers, void(const std::vector<std::string>&));
-
- MOCK_METHOD1(RegisterDataSource, void(const DataSourceDescriptor&));
- MOCK_METHOD1(UpdateDataSource, void(const DataSourceDescriptor&));
- MOCK_METHOD2(CommitData, void(const CommitDataRequest&, CommitDataCallback));
- MOCK_METHOD2(RegisterTraceWriter, void(uint32_t, uint32_t));
- MOCK_METHOD1(UnregisterTraceWriter, void(uint32_t));
- MOCK_METHOD1(Sync, void(std::function<void()>));
-};
-
TEST(LogHistogramTest, Simple) {
LogHistogram h;
h.Add(1);
diff --git a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
index 140a881..0d5e9c7 100644
--- a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
@@ -27,7 +27,7 @@
#include "src/base/test/test_task_runner.h"
#include "src/tracing/core/patch_list.h"
#include "src/tracing/test/aligned_buffer_test.h"
-#include "src/tracing/test/fake_producer_endpoint.h"
+#include "src/tracing/test/mock_producer_endpoint.h"
#include "test/gtest_and_gmock.h"
#include "protos/perfetto/trace/test_event.pbzero.h"
@@ -38,31 +38,8 @@
using testing::_;
using testing::Invoke;
using testing::Mock;
-
-class MockProducerEndpoint : public TracingService::ProducerEndpoint {
- public:
- void RegisterDataSource(const DataSourceDescriptor&) override {}
- void UpdateDataSource(const DataSourceDescriptor&) override {}
- void UnregisterDataSource(const std::string&) override {}
- void NotifyFlushComplete(FlushRequestID) override {}
- void NotifyDataSourceStarted(DataSourceInstanceID) override {}
- void NotifyDataSourceStopped(DataSourceInstanceID) override {}
- void ActivateTriggers(const std::vector<std::string>&) {}
- void Sync(std::function<void()>) override {}
- SharedMemory* shared_memory() const override { return nullptr; }
- size_t shared_buffer_page_size_kb() const override { return 0; }
- std::unique_ptr<TraceWriter> CreateTraceWriter(
- BufferID,
- BufferExhaustedPolicy) override {
- return nullptr;
- }
- SharedMemoryArbiter* MaybeSharedMemoryArbiter() override { return nullptr; }
- bool IsShmemProvidedByProducer() const override { return false; }
-
- MOCK_METHOD2(CommitData, void(const CommitDataRequest&, CommitDataCallback));
- MOCK_METHOD2(RegisterTraceWriter, void(uint32_t, uint32_t));
- MOCK_METHOD1(UnregisterTraceWriter, void(uint32_t));
-};
+using testing::NiceMock;
+using testing::UnorderedElementsAreArray;
class SharedMemoryArbiterImplTest : public AlignedBufferTest {
public:
@@ -83,7 +60,7 @@
std::unique_ptr<base::TestTaskRunner> task_runner_;
std::unique_ptr<SharedMemoryArbiterImpl> arbiter_;
- MockProducerEndpoint mock_producer_endpoint_;
+ NiceMock<MockProducerEndpoint> mock_producer_endpoint_;
std::function<void(const std::vector<uint32_t>&)> on_pages_complete_;
};
@@ -225,49 +202,23 @@
arbiter_->FlushPendingCommitDataRequests();
}
-// Helper for verifying trace writer id allocations.
-class TraceWriterIdChecker : public FakeProducerEndpoint {
- public:
- TraceWriterIdChecker(std::function<void()> checkpoint)
- : checkpoint_(std::move(checkpoint)) {}
-
- void RegisterTraceWriter(uint32_t id, uint32_t) override {
- EXPECT_GT(id, 0u);
- EXPECT_LE(id, kMaxWriterID);
- if (id > 0 && id <= kMaxWriterID) {
- registered_ids_.set(id - 1);
- }
- }
-
- void UnregisterTraceWriter(uint32_t id) override {
- if (++unregister_calls_ == kMaxWriterID)
- checkpoint_();
-
- EXPECT_GT(id, 0u);
- EXPECT_LE(id, kMaxWriterID);
- if (id > 0 && id <= kMaxWriterID) {
- unregistered_ids_.set(id - 1);
- }
- }
-
- // bit N corresponds to id N+1
- std::bitset<kMaxWriterID> registered_ids_;
- std::bitset<kMaxWriterID> unregistered_ids_;
-
- int unregister_calls_ = 0;
-
- private:
- std::function<void()> checkpoint_;
-};
-
// Check that we can actually create up to kMaxWriterID TraceWriter(s).
TEST_P(SharedMemoryArbiterImplTest, WriterIDsAllocation) {
auto checkpoint = task_runner_->CreateCheckpoint("last_unregistered");
- TraceWriterIdChecker id_checking_endpoint(checkpoint);
- arbiter_.reset(new SharedMemoryArbiterImpl(buf(), buf_size(), page_size(),
- &id_checking_endpoint,
- task_runner_.get()));
+ std::vector<uint32_t> registered_ids;
+ std::vector<uint32_t> unregistered_ids;
+
+ ON_CALL(mock_producer_endpoint_, RegisterTraceWriter)
+ .WillByDefault(
+ [&](uint32_t id, uint32_t) { registered_ids.push_back(id); });
+ ON_CALL(mock_producer_endpoint_, UnregisterTraceWriter)
+ .WillByDefault([&](uint32_t id) {
+ unregistered_ids.push_back(id);
+ if (unregistered_ids.size() == kMaxWriterID) {
+ checkpoint();
+ }
+ });
{
std::map<WriterID, std::unique_ptr<TraceWriter>> writers;
@@ -287,8 +238,11 @@
// memory arbiter.
task_runner_->RunUntilCheckpoint("last_unregistered", 15000);
- EXPECT_TRUE(id_checking_endpoint.registered_ids_.all());
- EXPECT_TRUE(id_checking_endpoint.unregistered_ids_.all());
+ std::vector<uint32_t> expected_ids; // 1..kMaxWriterID
+ for (uint32_t i = 1; i <= kMaxWriterID; i++)
+ expected_ids.push_back(i);
+ EXPECT_THAT(registered_ids, UnorderedElementsAreArray(expected_ids));
+ EXPECT_THAT(unregistered_ids, UnorderedElementsAreArray(expected_ids));
}
TEST_P(SharedMemoryArbiterImplTest, Shutdown) {
diff --git a/src/tracing/core/trace_writer_impl_unittest.cc b/src/tracing/core/trace_writer_impl_unittest.cc
index a0f3f3d..6750880 100644
--- a/src/tracing/core/trace_writer_impl_unittest.cc
+++ b/src/tracing/core/trace_writer_impl_unittest.cc
@@ -16,40 +16,66 @@
#include "src/tracing/core/trace_writer_impl.h"
+#include <vector>
+
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/commit_data_request.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/proto_utils.h"
#include "src/base/test/gtest_test_suite.h"
#include "src/base/test/test_task_runner.h"
#include "src/tracing/core/shared_memory_arbiter_impl.h"
#include "src/tracing/test/aligned_buffer_test.h"
-#include "src/tracing/test/fake_producer_endpoint.h"
+#include "src/tracing/test/mock_producer_endpoint.h"
#include "test/gtest_and_gmock.h"
+#include "protos/perfetto/trace/test_event.gen.h"
#include "protos/perfetto/trace/test_event.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.gen.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
namespace perfetto {
namespace {
+using ChunkHeader = SharedMemoryABI::ChunkHeader;
using ::testing::AllOf;
using ::testing::MockFunction;
using ::testing::Ne;
+using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::SizeIs;
using ::testing::ValuesIn;
class TraceWriterImplTest : public AlignedBufferTest {
public:
+ struct PatchKey {
+ uint32_t writer_id;
+ uint32_t chunk_id;
+ bool operator<(const PatchKey& other) const {
+ return std::tie(writer_id, chunk_id) <
+ std::tie(other.writer_id, other.chunk_id);
+ }
+ };
void SetUp() override {
SharedMemoryArbiterImpl::set_default_layout_for_testing(
SharedMemoryABI::PageLayout::kPageDiv4);
AlignedBufferTest::SetUp();
task_runner_.reset(new base::TestTaskRunner());
arbiter_.reset(new SharedMemoryArbiterImpl(buf(), buf_size(), page_size(),
- &fake_producer_endpoint_,
+ &mock_producer_endpoint_,
task_runner_.get()));
+ ON_CALL(mock_producer_endpoint_, CommitData)
+ .WillByDefault([&](const CommitDataRequest& req,
+ MockProducerEndpoint::CommitDataCallback cb) {
+ last_commit_ = req;
+ last_commit_callback_ = cb;
+ for (const CommitDataRequest::ChunkToPatch& c :
+ req.chunks_to_patch()) {
+ patches_[PatchKey{c.writer_id(), c.chunk_id()}] = c.patches();
+ }
+ });
}
void TearDown() override {
@@ -57,7 +83,99 @@
task_runner_.reset();
}
- FakeProducerEndpoint fake_producer_endpoint_;
+ std::vector<uint8_t> CopyPayloadAndApplyPatches(
+ SharedMemoryABI::Chunk& chunk) const {
+ std::vector<uint8_t> copy(chunk.payload_begin(),
+ chunk.payload_begin() + chunk.payload_size());
+ ChunkHeader::Packets p = chunk.header()->packets.load();
+
+ auto it = patches_.find(PatchKey{chunk.header()->writer_id.load(),
+ chunk.header()->chunk_id.load()});
+ if (it == patches_.end()) {
+ EXPECT_FALSE(p.flags & ChunkHeader::kChunkNeedsPatching);
+ return copy;
+ }
+ EXPECT_TRUE(p.flags & ChunkHeader::kChunkNeedsPatching);
+
+ for (const CommitDataRequest::ChunkToPatch::Patch& patch : it->second) {
+ if (patch.offset() + patch.data().size() > copy.size()) {
+ ADD_FAILURE() << "Patch out of bounds";
+ continue;
+ }
+ for (size_t i = 0; i < patch.data().size(); i++) {
+ copy[patch.offset() + i] =
+ reinterpret_cast<const uint8_t*>(patch.data().data())[i];
+ }
+ }
+ return copy;
+ }
+
+ // Extracts trace packets from the shared memory buffer, and returns copies of
+ // them (after applying the patches received). The producer that writes to the
+ // shared memory (i.e. the trace writer) must be destroyed.
+ std::vector<std::string> GetPacketsFromShmemAndPatches() {
+ std::vector<std::string> packets;
+ SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
+ bool was_fragmenting = false;
+ for (size_t page_idx = 0; page_idx < abi->num_pages(); page_idx++) {
+ uint32_t page_layout = abi->GetPageLayout(page_idx);
+ size_t num_chunks = SharedMemoryABI::GetNumChunksForLayout(page_layout);
+ for (size_t chunk_idx = 0; chunk_idx < num_chunks; chunk_idx++) {
+ SharedMemoryABI::ChunkState chunk_state =
+ abi->GetChunkState(page_idx, chunk_idx);
+ if (chunk_state != SharedMemoryABI::kChunkFree &&
+ chunk_state != SharedMemoryABI::kChunkComplete) {
+ ADD_FAILURE() << "Page " << page_idx << " chunk " << chunk_idx
+ << " unexpected state: " << chunk_state;
+ continue;
+ }
+ SharedMemoryABI::Chunk chunk =
+ abi->TryAcquireChunkForReading(page_idx, chunk_idx);
+ if (!chunk.is_valid())
+ continue;
+ ChunkHeader::Packets p = chunk.header()->packets.load();
+
+ EXPECT_EQ(
+ was_fragmenting,
+ static_cast<bool>(p.flags &
+ ChunkHeader::kFirstPacketContinuesFromPrevChunk));
+
+ std::vector<uint8_t> payload = CopyPayloadAndApplyPatches(chunk);
+
+ const uint8_t* read_ptr = payload.data();
+ const uint8_t* const end_read_ptr = payload.data() + payload.size();
+
+ size_t num_fragments = p.count;
+ for (; num_fragments && read_ptr < end_read_ptr; num_fragments--) {
+ uint64_t len;
+ read_ptr =
+ protozero::proto_utils::ParseVarInt(read_ptr, end_read_ptr, &len);
+ if (!was_fragmenting || packets.empty()) {
+ packets.push_back(std::string());
+ }
+ if (read_ptr + len > end_read_ptr) {
+ ADD_FAILURE() << "Page " << page_idx << " chunk " << chunk_idx
+ << " malformed chunk";
+ }
+ packets.back().append(reinterpret_cast<const char*>(read_ptr),
+ static_cast<size_t>(len));
+ read_ptr += len;
+ }
+ EXPECT_EQ(num_fragments, 0u);
+ if (p.flags & ChunkHeader::kLastPacketContinuesOnNextChunk) {
+ was_fragmenting = true;
+ }
+ }
+ }
+ return packets;
+ }
+
+ CommitDataRequest last_commit_;
+ ProducerEndpoint::CommitDataCallback last_commit_callback_;
+ std::map<PatchKey, std::vector<CommitDataRequest::ChunkToPatch::Patch>>
+ patches_;
+ NiceMock<MockProducerEndpoint> mock_producer_endpoint_;
+
std::unique_ptr<base::TestTaskRunner> task_runner_;
std::unique_ptr<SharedMemoryArbiterImpl> arbiter_;
};
@@ -65,7 +183,7 @@
size_t const kPageSizes[] = {4096, 65536};
INSTANTIATE_TEST_SUITE_P(PageSize, TraceWriterImplTest, ValuesIn(kPageSizes));
-TEST_P(TraceWriterImplTest, SingleWriter) {
+TEST_P(TraceWriterImplTest, NewTracePacket) {
const BufferID kBufId = 42;
std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(kBufId);
const size_t kNumPackets = 32;
@@ -79,31 +197,21 @@
// and the chunk to be put back in the kChunkComplete state.
writer.reset();
- SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
- size_t packets_count = 0;
- for (size_t page_idx = 0; page_idx < abi->num_pages(); page_idx++) {
- uint32_t page_layout = abi->GetPageLayout(page_idx);
- size_t num_chunks = SharedMemoryABI::GetNumChunksForLayout(page_layout);
- for (size_t chunk_idx = 0; chunk_idx < num_chunks; chunk_idx++) {
- auto chunk_state = abi->GetChunkState(page_idx, chunk_idx);
- ASSERT_TRUE(chunk_state == SharedMemoryABI::kChunkFree ||
- chunk_state == SharedMemoryABI::kChunkComplete);
- auto chunk = abi->TryAcquireChunkForReading(page_idx, chunk_idx);
- if (!chunk.is_valid())
- continue;
- packets_count += chunk.header()->packets.load().count;
- }
+ std::vector<std::string> packets = GetPacketsFromShmemAndPatches();
+ ASSERT_THAT(packets, SizeIs(kNumPackets));
+ for (size_t i = 0; i < kNumPackets; i++) {
+ protos::gen::TracePacket packet;
+ packet.ParseFromString(packets[i]);
+ EXPECT_EQ(packet.for_testing().str(), "foobar " + std::to_string(i));
}
- EXPECT_EQ(packets_count, kNumPackets);
- // TODO(primiano): check also the content of the packets decoding the protos.
}
TEST_P(TraceWriterImplTest, FragmentingPacketWithProducerAndServicePatching) {
const BufferID kBufId = 42;
std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(kBufId);
- // Write a packet that's guaranteed to span more than a single chunk, but less
- // than two chunks.
+ // Write a packet that's guaranteed to span more than a single chunk, but
+ // less than two chunks.
auto packet = writer->NewTracePacket();
size_t chunk_size = page_size() / 4;
std::string large_string(chunk_size, 'x');
@@ -111,15 +219,14 @@
// First chunk should be committed.
arbiter_->FlushPendingCommitDataRequests();
- const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].target_buffer(), kBufId);
- EXPECT_THAT(last_commit.chunks_to_patch(), SizeIs(0));
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].target_buffer(), kBufId);
+ EXPECT_THAT(last_commit_.chunks_to_patch(), SizeIs(0));
- // We will simulate a batching cycle by first setting the batching period to a
- // very large value and then force-flushing when we are done writing data.
+ // We will simulate a batching cycle by first setting the batching period to
+ // a very large value and then force-flushing when we are done writing data.
arbiter_->SetDirectSMBPatchingSupportedByService();
ASSERT_TRUE(arbiter_->EnableDirectSMBPatching());
arbiter_->SetBatchCommitsDuration(UINT32_MAX);
@@ -145,8 +252,8 @@
SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
// The first allocated chunk should be complete but need patching, since the
- // packet extended past the chunk and no patches for the packet size or string
- // field size were applied yet.
+ // packet extended past the chunk and no patches for the packet size or
+ // string field size were applied yet.
ASSERT_EQ(abi->GetChunkState(0u, 0u), SharedMemoryABI::kChunkComplete);
auto chunk = abi->TryAcquireChunkForReading(0u, 0u);
ASSERT_TRUE(chunk.is_valid());
@@ -157,19 +264,19 @@
SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
// Verify that a patch for the first chunk was sent to the service.
- ASSERT_THAT(last_commit.chunks_to_patch(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_patch()[0].writer_id(), writer->writer_id());
- EXPECT_EQ(last_commit.chunks_to_patch()[0].target_buffer(), kBufId);
- EXPECT_EQ(last_commit.chunks_to_patch()[0].chunk_id(),
+ ASSERT_THAT(last_commit_.chunks_to_patch(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].writer_id(), writer->writer_id());
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].target_buffer(), kBufId);
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].chunk_id(),
chunk.header()->chunk_id.load());
- EXPECT_FALSE(last_commit.chunks_to_patch()[0].has_more_patches());
- EXPECT_THAT(last_commit.chunks_to_patch()[0].patches(), SizeIs(1));
+ EXPECT_FALSE(last_commit_.chunks_to_patch()[0].has_more_patches());
+ EXPECT_THAT(last_commit_.chunks_to_patch()[0].patches(), SizeIs(1));
// Verify that the second chunk was committed.
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 1u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].target_buffer(), kBufId);
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 1u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].target_buffer(), kBufId);
// The second chunk should be in a complete state and should not need
// patching, as the patches to it should have been applied in the producer.
@@ -184,9 +291,9 @@
}
TEST_P(TraceWriterImplTest, FragmentingPacketWithoutEnablingProducerPatching) {
- // We will simulate a batching cycle by first setting the batching period to a
- // very large value and will force flush to simulate a flush happening when we
- // believe it should - in this case when a patch is encountered.
+ // We will simulate a batching cycle by first setting the batching period to
+ // a very large value and will force flush to simulate a flush happening
+ // when we believe it should - in this case when a patch is encountered.
//
// Note: direct producer-side patching should be disabled by default.
arbiter_->SetBatchCommitsDuration(UINT32_MAX);
@@ -207,8 +314,8 @@
arbiter_->FlushPendingCommitDataRequests();
// The first allocated chunk should be complete but need patching, since the
- // packet extended past the chunk and no patches for the packet size or string
- // field size were applied in the producer.
+ // packet extended past the chunk and no patches for the packet size or
+ // string field size were applied in the producer.
SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
ASSERT_EQ(abi->GetChunkState(0u, 0u), SharedMemoryABI::kChunkComplete);
auto chunk = abi->TryAcquireChunkForReading(0u, 0u);
@@ -220,25 +327,24 @@
SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
// The first chunk was committed.
- const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].target_buffer(), kBufId);
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].target_buffer(), kBufId);
// The patches for the first chunk were committed.
- ASSERT_THAT(last_commit.chunks_to_patch(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_patch()[0].writer_id(), writer->writer_id());
- EXPECT_EQ(last_commit.chunks_to_patch()[0].target_buffer(), kBufId);
- EXPECT_EQ(last_commit.chunks_to_patch()[0].chunk_id(),
+ ASSERT_THAT(last_commit_.chunks_to_patch(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].writer_id(), writer->writer_id());
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].target_buffer(), kBufId);
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].chunk_id(),
chunk.header()->chunk_id.load());
- EXPECT_FALSE(last_commit.chunks_to_patch()[0].has_more_patches());
- EXPECT_THAT(last_commit.chunks_to_patch()[0].patches(), SizeIs(1));
+ EXPECT_FALSE(last_commit_.chunks_to_patch()[0].has_more_patches());
+ EXPECT_THAT(last_commit_.chunks_to_patch()[0].patches(), SizeIs(1));
}
-// Sets up a scenario in which the SMB is exhausted and TraceWriter fails to get
-// a new chunk while fragmenting a packet. Verifies that data is dropped until
-// the SMB is freed up and TraceWriter can get a new chunk.
+// Sets up a scenario in which the SMB is exhausted and TraceWriter fails to
+// get a new chunk while fragmenting a packet. Verifies that data is dropped
+// until the SMB is freed up and TraceWriter can get a new chunk.
TEST_P(TraceWriterImplTest, FragmentingPacketWhileBufferExhausted) {
const BufferID kBufId = 42;
std::unique_ptr<TraceWriter> writer =
@@ -260,8 +366,8 @@
->drop_packets_for_testing());
}
- // Write a packet that's guaranteed to span more than a single chunk, causing
- // |writer| to attempt to acquire a new chunk but fail to do so.
+ // Write a packet that's guaranteed to span more than a single chunk,
+ // causing |writer| to attempt to acquire a new chunk but fail to do so.
auto packet2 = writer->NewTracePacket();
size_t chunk_size = page_size() / 4;
std::string large_string(chunk_size, 'x');
@@ -272,12 +378,11 @@
// First chunk should be committed.
arbiter_->FlushPendingCommitDataRequests();
- const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].target_buffer(), kBufId);
- EXPECT_THAT(last_commit.chunks_to_patch(), SizeIs(0));
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].target_buffer(), kBufId);
+ EXPECT_THAT(last_commit_.chunks_to_patch(), SizeIs(0));
// It should not need patching and not have the continuation flag set.
SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
@@ -307,18 +412,19 @@
EXPECT_FALSE(reinterpret_cast<TraceWriterImpl*>(writer.get())
->drop_packets_for_testing());
- // The first packet in the chunk should have the previous_packet_dropped flag
- // set, so shouldn't be empty.
+ // The first packet in the chunk should have the previous_packet_dropped
+ // flag set, so shouldn't be empty.
EXPECT_GT(packet4->Finalize(), 0u);
// Flushing the writer causes the chunk to be released again.
writer->Flush();
- EXPECT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 0u);
- EXPECT_THAT(last_commit.chunks_to_patch(), SizeIs(0));
+ EXPECT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 0u);
+ EXPECT_THAT(last_commit_.chunks_to_patch(), SizeIs(0));
- // Chunk should contain only |packet4| and not have any continuation flag set.
+ // Chunk should contain only |packet4| and not have any continuation flag
+ // set.
ASSERT_EQ(abi->GetChunkState(0u, 0u), SharedMemoryABI::kChunkComplete);
chunk = abi->TryAcquireChunkForReading(0u, 0u);
ASSERT_TRUE(chunk.is_valid());
@@ -333,8 +439,8 @@
}
// Verifies that a TraceWriter that is flushed before the SMB is full and then
-// acquires a garbage chunk later recovers and writes a previous_packet_dropped
-// marker into the trace.
+// acquires a garbage chunk later recovers and writes a
+// previous_packet_dropped marker into the trace.
TEST_P(TraceWriterImplTest, FlushBeforeBufferExhausted) {
const BufferID kBufId = 42;
std::unique_ptr<TraceWriter> writer =
@@ -352,10 +458,9 @@
// First chunk should be committed. Don't release it as free just yet.
arbiter_->FlushPendingCommitDataRequests();
- const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 0u);
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 0u);
// Grab all the remaining chunks in the SMB in new writers.
std::array<std::unique_ptr<TraceWriter>, kNumPages * 4 - 1> other_writers;
@@ -402,18 +507,19 @@
EXPECT_FALSE(reinterpret_cast<TraceWriterImpl*>(writer.get())
->drop_packets_for_testing());
- // The first packet in the chunk should have the previous_packet_dropped flag
- // set, so shouldn't be empty.
+ // The first packet in the chunk should have the previous_packet_dropped
+ // flag set, so shouldn't be empty.
EXPECT_GT(packet4->Finalize(), 0u);
// Flushing the writer causes the chunk to be released again.
writer->Flush();
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_move()[0].page(), 0u);
- EXPECT_EQ(last_commit.chunks_to_move()[0].chunk(), 0u);
- EXPECT_THAT(last_commit.chunks_to_patch(), SizeIs(0));
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].page(), 0u);
+ EXPECT_EQ(last_commit_.chunks_to_move()[0].chunk(), 0u);
+ EXPECT_THAT(last_commit_.chunks_to_patch(), SizeIs(0));
- // Chunk should contain only |packet4| and not have any continuation flag set.
+ // Chunk should contain only |packet4| and not have any continuation flag
+ // set.
ASSERT_EQ(SharedMemoryABI::kChunkComplete, abi->GetChunkState(0u, 0u));
chunk = abi->TryAcquireChunkForReading(0u, 0u);
ASSERT_TRUE(chunk.is_valid());
@@ -427,9 +533,9 @@
SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
}
-// Regression test that verifies that flushing a TraceWriter while a fragmented
-// packet still has uncommitted patches doesn't hit a DCHECK / crash the writer
-// thread.
+// Regression test that verifies that flushing a TraceWriter while a
+// fragmented packet still has uncommitted patches doesn't hit a DCHECK /
+// crash the writer thread.
TEST_P(TraceWriterImplTest, FlushAfterFragmentingPacketWhileBufferExhausted) {
const BufferID kBufId = 42;
std::unique_ptr<TraceWriter> writer =
@@ -464,11 +570,10 @@
// First two chunks should be committed.
arbiter_->FlushPendingCommitDataRequests();
- const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
- ASSERT_THAT(last_commit.chunks_to_move(), SizeIs(2));
+ ASSERT_THAT(last_commit_.chunks_to_move(), SizeIs(2));
- // Flushing should succeed, even though some patches are still in the writer's
- // patch list.
+ // Flushing should succeed, even though some patches are still in the
+ // writer's patch list.
packet2->Finalize();
writer->Flush();
}
@@ -484,11 +589,11 @@
}
EXPECT_CALL(flush_cb, Call).Times(0);
- ASSERT_FALSE(fake_producer_endpoint_.last_commit_data_callback);
+ ASSERT_FALSE(last_commit_callback_);
writer->Flush(flush_cb.AsStdFunction());
- ASSERT_TRUE(fake_producer_endpoint_.last_commit_data_callback);
+ ASSERT_TRUE(last_commit_callback_);
EXPECT_CALL(flush_cb, Call).Times(1);
- fake_producer_endpoint_.last_commit_data_callback();
+ last_commit_callback_();
}
TEST_P(TraceWriterImplTest, NestedMsgsPatches) {
@@ -539,12 +644,11 @@
arbiter_->FlushPendingCommitDataRequests();
- const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
- ASSERT_THAT(last_commit.chunks_to_patch(), SizeIs(1));
- EXPECT_EQ(last_commit.chunks_to_patch()[0].writer_id(), writer->writer_id());
- EXPECT_EQ(last_commit.chunks_to_patch()[0].target_buffer(), kBufId);
- EXPECT_FALSE(last_commit.chunks_to_patch()[0].has_more_patches());
- EXPECT_THAT(last_commit.chunks_to_patch()[0].patches(), SizeIs(3));
+ ASSERT_THAT(last_commit_.chunks_to_patch(), SizeIs(1));
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].writer_id(), writer->writer_id());
+ EXPECT_EQ(last_commit_.chunks_to_patch()[0].target_buffer(), kBufId);
+ EXPECT_FALSE(last_commit_.chunks_to_patch()[0].has_more_patches());
+ EXPECT_THAT(last_commit_.chunks_to_patch()[0].patches(), SizeIs(3));
}
// TODO(primiano): add multi-writer test.
diff --git a/src/tracing/test/BUILD.gn b/src/tracing/test/BUILD.gn
index fc63b18..78b1d6c 100644
--- a/src/tracing/test/BUILD.gn
+++ b/src/tracing/test/BUILD.gn
@@ -50,7 +50,7 @@
# has no implementation for Windows or NaCL.
if (!is_win && !is_nacl) {
sources += [
- "fake_producer_endpoint.h",
+ "mock_producer_endpoint.h",
"mock_consumer.cc",
"mock_consumer.h",
"mock_producer.cc",
diff --git a/src/tracing/test/fake_producer_endpoint.h b/src/tracing/test/fake_producer_endpoint.h
deleted file mode 100644
index fa75e4a..0000000
--- a/src/tracing/test/fake_producer_endpoint.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#ifndef SRC_TRACING_TEST_FAKE_PRODUCER_ENDPOINT_H_
-#define SRC_TRACING_TEST_FAKE_PRODUCER_ENDPOINT_H_
-
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-
-namespace perfetto {
-
-class FakeProducerEndpoint : public TracingService::ProducerEndpoint {
- public:
- void RegisterDataSource(const DataSourceDescriptor&) override {}
- void UpdateDataSource(const DataSourceDescriptor&) override {}
- void UnregisterDataSource(const std::string&) override {}
- void RegisterTraceWriter(uint32_t, uint32_t) override {}
- void UnregisterTraceWriter(uint32_t) override {}
- void CommitData(const CommitDataRequest& req,
- CommitDataCallback callback) override {
- last_commit_data_request = req;
- last_commit_data_callback = callback;
- }
- void NotifyFlushComplete(FlushRequestID) override {}
- void NotifyDataSourceStarted(DataSourceInstanceID) override {}
- void NotifyDataSourceStopped(DataSourceInstanceID) override {}
- void ActivateTriggers(const std::vector<std::string>&) override {}
- void Sync(std::function<void()>) override {}
- SharedMemory* shared_memory() const override { return nullptr; }
- size_t shared_buffer_page_size_kb() const override { return 0; }
- std::unique_ptr<TraceWriter> CreateTraceWriter(
- BufferID,
- BufferExhaustedPolicy) override {
- return nullptr;
- }
- SharedMemoryArbiter* MaybeSharedMemoryArbiter() override { return nullptr; }
- bool IsShmemProvidedByProducer() const override { return false; }
-
- CommitDataRequest last_commit_data_request;
- CommitDataCallback last_commit_data_callback;
-};
-
-} // namespace perfetto
-
-#endif // SRC_TRACING_TEST_FAKE_PRODUCER_ENDPOINT_H_
diff --git a/src/tracing/test/mock_producer_endpoint.h b/src/tracing/test/mock_producer_endpoint.h
new file mode 100644
index 0000000..d3232e7
--- /dev/null
+++ b/src/tracing/test/mock_producer_endpoint.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#ifndef SRC_TRACING_TEST_MOCK_PRODUCER_ENDPOINT_H_
+#define SRC_TRACING_TEST_MOCK_PRODUCER_ENDPOINT_H_
+
+#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "protos/perfetto/common/data_source_descriptor.gen.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+
+class MockProducerEndpoint : public TracingService::ProducerEndpoint {
+ public:
+ MOCK_METHOD1(RegisterDataSource, void(const DataSourceDescriptor&));
+ MOCK_METHOD1(UpdateDataSource, void(const DataSourceDescriptor&));
+ MOCK_METHOD1(UnregisterDataSource, void(const std::string&));
+ MOCK_METHOD2(RegisterTraceWriter, void(uint32_t, uint32_t));
+ MOCK_METHOD1(UnregisterTraceWriter, void(uint32_t));
+ MOCK_METHOD2(CommitData, void(const CommitDataRequest&, CommitDataCallback));
+ MOCK_CONST_METHOD0(shared_memory, SharedMemory*());
+ MOCK_CONST_METHOD0(shared_buffer_page_size_kb, size_t());
+ MOCK_METHOD2(CreateTraceWriter,
+ std::unique_ptr<TraceWriter>(BufferID, BufferExhaustedPolicy));
+ MOCK_METHOD0(MaybeSharedMemoryArbiter, SharedMemoryArbiter*());
+ MOCK_CONST_METHOD0(IsShmemProvidedByProducer, bool());
+ MOCK_METHOD1(NotifyFlushComplete, void(FlushRequestID));
+ MOCK_METHOD1(NotifyDataSourceStarted, void(DataSourceInstanceID));
+ MOCK_METHOD1(NotifyDataSourceStopped, void(DataSourceInstanceID));
+ MOCK_METHOD1(ActivateTriggers, void(const std::vector<std::string>&));
+ MOCK_METHOD1(Sync, void(std::function<void()>));
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACING_TEST_MOCK_PRODUCER_ENDPOINT_H_
diff --git a/tools/record_android_trace b/tools/record_android_trace
index f2931ed..c5fc03a 100755
--- a/tools/record_android_trace
+++ b/tools/record_android_trace
@@ -107,6 +107,9 @@
help = 'Don\'t run `adb root` run as user (only when sideloading)'
parser.add_argument('-u', '--user', action='store_true', help=help)
+ help = 'Specify the ADB device serial'
+ parser.add_argument('--serial', '-s', default=None, help=help)
+
grp = parser.add_argument_group(
'Short options: (only when not using -c/--config)')
@@ -144,9 +147,6 @@
help = 'Can be generated with https://ui.perfetto.dev/#!/record'
grp.add_argument('-c', '--config', default=None, help=help)
- help = 'Specify the ADB device serial'
- grp.add_argument('--serial', '-s', default=None, help=help)
-
args = parser.parse_args()
args.sideload = args.sideload or args.sideload_path is not None