trace writer: Send patches after completing fragmented packet

For scraping of incomplete chunks in the service to be useful, we
should ensure that prior completed chunks are patched as soon as
possible. Otherwise, the incomplete chunk's data can't be used by the
service because the prior chunk is still awaiting patches.

Thus, send the patches for previous chunks when a fragmented packet was
completed.

Bug: 73828976
Change-Id: Ia5879f47f2662061695e7a9a44da16ab4d1bef33
diff --git a/src/tracing/core/trace_writer_impl_unittest.cc b/src/tracing/core/trace_writer_impl_unittest.cc
index 2b5197b..f9a9230 100644
--- a/src/tracing/core/trace_writer_impl_unittest.cc
+++ b/src/tracing/core/trace_writer_impl_unittest.cc
@@ -32,11 +32,14 @@
 namespace {
 
 class FakeProducerEndpoint : public TracingService::ProducerEndpoint {
+ public:
   void RegisterDataSource(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&, CommitDataCallback) override {}
+  void CommitData(const CommitDataRequest& req, CommitDataCallback) override {
+    last_commit_data_request = req;
+  }
   void NotifyFlushComplete(FlushRequestID) override {}
   void NotifyDataSourceStopped(DataSourceInstanceID) override {}
   SharedMemory* shared_memory() const override { return nullptr; }
@@ -44,6 +47,8 @@
   std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override {
     return nullptr;
   }
+
+  CommitDataRequest last_commit_data_request;
 };
 
 class TraceWriterImplTest : public AlignedBufferTest {
@@ -121,13 +126,22 @@
   std::string large_string = large_string_writer.str();
   packet->set_for_testing()->set_str(large_string.data(), large_string.size());
 
+  // First chunk should be committed.
+  arbiter_->FlushPendingCommitDataRequests();
+  const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
+  ASSERT_EQ(1, last_commit.chunks_to_move_size());
+  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].page());
+  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].chunk());
+  EXPECT_EQ(kBufId, last_commit.chunks_to_move()[0].target_buffer());
+  EXPECT_EQ(0, last_commit.chunks_to_patch_size());
+
   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.
-  ASSERT_EQ(SharedMemoryABI::kChunkComplete, abi->GetChunkState(0, 0));
-  auto chunk = abi->TryAcquireChunkForReading(0, 0);
+  ASSERT_EQ(SharedMemoryABI::kChunkComplete, abi->GetChunkState(0u, 0u));
+  auto chunk = abi->TryAcquireChunkForReading(0u, 0u);
   ASSERT_TRUE(chunk.is_valid());
   ASSERT_EQ(1, chunk.header()->packets.load().count);
   ASSERT_TRUE(chunk.header()->packets.load().flags &
@@ -135,8 +149,18 @@
   ASSERT_TRUE(chunk.header()->packets.load().flags &
               SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
 
-  // TODO(eseckler): Also verify that the next commit contains patch entries for
-  // the packet size and string field size.
+  // Starting a new packet should cause patches to be applied.
+  packet->Finalize();
+  auto packet2 = writer->NewTracePacket();
+  arbiter_->FlushPendingCommitDataRequests();
+  EXPECT_EQ(0, last_commit.chunks_to_move_size());
+  ASSERT_EQ(1, last_commit.chunks_to_patch_size());
+  EXPECT_EQ(writer->writer_id(), last_commit.chunks_to_patch()[0].writer_id());
+  EXPECT_EQ(kBufId, last_commit.chunks_to_patch()[0].target_buffer());
+  EXPECT_EQ(chunk.header()->chunk_id.load(),
+            last_commit.chunks_to_patch()[0].chunk_id());
+  EXPECT_FALSE(last_commit.chunks_to_patch()[0].has_more_patches());
+  ASSERT_EQ(1, last_commit.chunks_to_patch()[0].patches_size());
 }
 
 // TODO(primiano): add multi-writer test.