pw_rpc: Rework the FakeChannelOutput classes

- Update Raw/NanopbFakeChannelOutput so it can be used for both client
  and service testing. Record all packets sent and support iterating
  over payloads by RPC. Store payloads in a single buffer rather than a
  list of fixed-size buffers to support different payload sizes with
  less memory.
- Allow encoding/decoding individual proto methods with NanopbSerde.
- Update tests to use the new FakeChannelOutput API.
- Adapt the test method contexts to use the new FakeChannelOutput. A
  test server class with improved functionality (and no macros) will be
  created in the future.

Requires: pigweed-internal:16580
Change-Id: I10eb11cdf8e7a3ee656d2a00d5a6517bc0179281
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/64962
Commit-Queue: Wyatt Hepler <hepler@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_rpc/fake_channel_output.cc b/pw_rpc/fake_channel_output.cc
index 7c0a9e5..4f688e8 100644
--- a/pw_rpc/fake_channel_output.cc
+++ b/pw_rpc/fake_channel_output.cc
@@ -15,23 +15,24 @@
 #include "pw_rpc/internal/fake_channel_output.h"
 
 #include "pw_assert/check.h"
+#include "pw_log/log.h"
 #include "pw_result/result.h"
 #include "pw_rpc/internal/packet.h"
 
 namespace pw::rpc::internal::test {
 
 void FakeChannelOutput::clear() {
-  ClearResponses();
+  payloads_.clear();
+  packets_.clear();
   total_response_packets_ = 0;
   total_stream_packets_ = 0;
-  last_status_ = Status::Unknown();
   send_status_ = OkStatus();
   return_after_packet_count_ = -1;
 }
 
 Status FakeChannelOutput::SendAndReleaseBuffer(
     std::span<const std::byte> buffer) {
-  PW_CHECK_PTR_EQ(buffer.data(), packet_buffer_.data());
+  PW_CHECK_PTR_EQ(buffer.data(), encoding_buffer_.data());
 
   // If the buffer is empty, this is just releasing an unused buffer.
   if (buffer.empty()) {
@@ -51,20 +52,22 @@
   Result<Packet> result = Packet::FromBuffer(buffer);
   PW_CHECK_OK(result.status());
 
-  last_status_ = result.value().status();
+  PW_CHECK(!packets_.full(),
+           "Attempted to store more than %u packets. Increase the kMaxPackets "
+           "template arg to store more packets.",
+           static_cast<unsigned>(packets_.size()));
+
+  packets_.push_back(*result);
+
+  CopyPayloadToBuffer(packets_.back().payload());
 
   switch (result.value().type()) {
     case PacketType::RESPONSE:
-      // Server streaming RPCs don't have a payload in their response packet.
-      if (!HasServerStream(method_type_)) {
-        ProcessResponse(result.value().payload());
-      }
       ++total_response_packets_;
       break;
     case PacketType::SERVER_ERROR:
       PW_CRASH("Server error: %s", result.value().status().str());
     case PacketType::SERVER_STREAM:
-      ProcessResponse(result.value().payload());
       ++total_stream_packets_;
       break;
     default:
@@ -74,4 +77,22 @@
   return OkStatus();
 }
 
+void FakeChannelOutput::CopyPayloadToBuffer(const ConstByteSpan& payload) {
+  if (payload.empty()) {
+    return;
+  }
+
+  const size_t available_bytes = payloads_.max_size() - payloads_.size();
+  PW_CHECK_UINT_GE(available_bytes,
+                   payload.size(),
+                   "Ran out of payload buffer space. Increase "
+                   "kPayloadBufferSizeBytes (%u) or use smaller payloads.",
+                   static_cast<unsigned>(payloads_.max_size()));
+
+  const size_t start = payloads_.size();
+  payloads_.resize(payloads_.size() + payload.size());
+  std::memcpy(&payloads_[start], payload.data(), payload.size());
+  packets_.back().set_payload(std::span(&payloads_[start], payload.size()));
+}
+
 }  // namespace pw::rpc::internal::test