pw_rpc: Generic method invocations and tests

- Restructure the BUILD.gn file to define the pw_rpc server library with
  a template. This makes it simple to build different versions of the
  pw_rpc server library.
- Define the ServerContext class, which provides context for a
  particular RPC invocation.
- Have the server invoke RPCs if it finds a method with matching IDs.
- Implement a test version of the Method class and expand the server
  tests.

Change-Id: Id1f46a88f2618a649d72f8c694ee829aef80588c
diff --git a/pw_rpc/server_test.cc b/pw_rpc/server_test.cc
index 984f5d1..b242088 100644
--- a/pw_rpc/server_test.cc
+++ b/pw_rpc/server_test.cc
@@ -14,15 +14,22 @@
 
 #include "pw_rpc/server.h"
 
+#include <array>
+#include <cstdint>
+
 #include "gtest/gtest.h"
+#include "pw_assert/assert.h"
 #include "pw_rpc/internal/packet.h"
+#include "pw_rpc/internal/service.h"
 
 namespace pw::rpc {
 namespace {
 
+using std::byte;
+
+using internal::Method;
 using internal::Packet;
 using internal::PacketType;
-using std::byte;
 
 template <size_t buffer_size>
 class TestOutput : public ChannelOutput {
@@ -42,106 +49,153 @@
   span<const byte> sent_packet_;
 };
 
-Packet MakePacket(uint32_t channel_id,
-                  uint32_t service_id,
-                  uint32_t method_id,
-                  span<const byte> payload) {
-  Packet packet(PacketType::RPC);
-  packet.set_channel_id(channel_id);
-  packet.set_service_id(service_id);
-  packet.set_method_id(method_id);
-  packet.set_payload(payload);
-  return packet;
+class TestService : public internal::Service {
+ public:
+  TestService(uint32_t service_id)
+      : internal::Service(service_id, methods_),
+        methods_{
+            Method(100),
+            Method(200),
+        } {}
+
+  Method& method(uint32_t id) {
+    for (Method& method : methods_) {
+      if (method.id() == id) {
+        return method;
+      }
+    }
+
+    PW_CRASH("Invalid method ID %u", static_cast<unsigned>(id));
+  }
+
+ private:
+  std::array<Method, 2> methods_;
+};
+
+class BasicServer : public ::testing::Test {
+ protected:
+  static constexpr byte kDefaultPayload[] = {
+      byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
+
+  BasicServer()
+      : output_(1),
+        channels_{
+            Channel::Create<1>(&output_),
+            Channel::Create<2>(&output_),
+            Channel(),  // available for assignment
+        },
+        server_(channels_),
+        service_(42) {
+    server_.RegisterService(service_);
+  }
+
+  TestOutput<128> output_;
+  std::array<Channel, 3> channels_;
+  Server server_;
+  TestService service_;
+
+  span<const byte> EncodeRequest(PacketType type,
+                                 uint32_t channel_id,
+                                 uint32_t service_id,
+                                 uint32_t method_id,
+                                 span<const byte> payload = kDefaultPayload) {
+    auto sws = Packet(type, channel_id, service_id, method_id, payload)
+                   .Encode(request_buffer_);
+    EXPECT_EQ(Status::OK, sws.status());
+    return span(request_buffer_, sws.size());
+  }
+
+ private:
+  byte request_buffer_[64];
+};
+
+TEST_F(BasicServer, ProcessPacket_ValidMethod_InvokesMethod) {
+  server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 100), output_);
+
+  const Method& method = service_.method(100);
+  EXPECT_EQ(1u, method.last_channel_id());
+  EXPECT_EQ(sizeof(kDefaultPayload), method.last_request().size());
+  EXPECT_EQ(std::memcmp(kDefaultPayload,
+                        method.last_request().data(),
+                        method.last_request().size()),
+            0);
 }
 
-TEST(Server, ProcessPacket_SendsResponse) {
-  TestOutput<128> output(1);
-  Channel channels[] = {
-      Channel::Create<1>(&output),
-      Channel::Create<2>(&output),
-  };
-  Server server(channels);
-  internal::Service service(42, {});
-  server.RegisterService(service);
+TEST_F(BasicServer, ProcessPacket_ValidMethod_SendsOkResponse) {
+  server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 100), output_);
 
-  byte encoded_packet[64];
-  constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
-  Packet request = MakePacket(1, 42, 27, payload);
-  auto sws = request.Encode(encoded_packet);
-
-  server.ProcessPacket(span(encoded_packet, sws.size()), output);
-  Packet packet = Packet::FromBuffer(output.sent_packet());
-  EXPECT_EQ(packet.status(), Status::OK);
+  Packet packet = Packet::FromBuffer(output_.sent_packet());
   EXPECT_EQ(packet.channel_id(), 1u);
   EXPECT_EQ(packet.service_id(), 42u);
+  EXPECT_EQ(packet.method_id(), 100u);
+  EXPECT_TRUE(packet.payload().empty());
+  EXPECT_EQ(packet.status(), Status::OK);
 }
 
-TEST(Server, ProcessPacket_SendsNotFoundOnInvalidService) {
-  TestOutput<128> output(1);
-  Channel channels[] = {
-      Channel::Create<1>(&output),
-      Channel::Create<2>(&output),
-  };
-  Server server(channels);
-  internal::Service service(42, {});
-  server.RegisterService(service);
+TEST_F(BasicServer, ProcessPacket_ValidMethod_SendsErrorResponse) {
+  constexpr byte resp[] = {byte{0xf0}, byte{0x0d}};
+  service_.method(200).set_response(resp);
+  service_.method(200).set_status(Status::FAILED_PRECONDITION);
 
-  byte encoded_packet[64];
-  constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
-  Packet request = MakePacket(1, 43, 27, payload);
-  auto sws = request.Encode(encoded_packet);
+  server_.ProcessPacket(EncodeRequest(PacketType::RPC, 2, 42, 200), output_);
 
-  server.ProcessPacket(span(encoded_packet, sws.size()), output);
-  Packet packet = Packet::FromBuffer(output.sent_packet());
+  Packet packet = Packet::FromBuffer(output_.sent_packet());
+  EXPECT_EQ(packet.channel_id(), 2u);
+  EXPECT_EQ(packet.service_id(), 42u);
+  EXPECT_EQ(packet.method_id(), 200u);
+  EXPECT_EQ(packet.status(), Status::FAILED_PRECONDITION);
+  ASSERT_EQ(sizeof(resp), packet.payload().size());
+  EXPECT_EQ(std::memcmp(packet.payload().data(), resp, sizeof(resp)), 0);
+}
+
+TEST_F(BasicServer, ProcessPacket_InvalidMethod_NothingIsInvoked) {
+  server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 101), output_);
+
+  EXPECT_EQ(0u, service_.method(100).last_channel_id());
+  EXPECT_EQ(0u, service_.method(200).last_channel_id());
+}
+
+TEST_F(BasicServer, ProcessPacket_InvalidMethod_SendsNotFound) {
+  server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 42, 27), output_);
+
+  Packet packet = Packet::FromBuffer(output_.sent_packet());
+  EXPECT_EQ(packet.channel_id(), 1u);
+  EXPECT_EQ(packet.service_id(), 42u);
+  EXPECT_EQ(packet.method_id(), 0u);  // No method ID 27
+  EXPECT_EQ(packet.status(), Status::NOT_FOUND);
+}
+
+TEST_F(BasicServer, ProcessPacket_InvalidService_SendsNotFound) {
+  server_.ProcessPacket(EncodeRequest(PacketType::RPC, 1, 43, 27), output_);
+
+  Packet packet = Packet::FromBuffer(output_.sent_packet());
   EXPECT_EQ(packet.status(), Status::NOT_FOUND);
   EXPECT_EQ(packet.channel_id(), 1u);
   EXPECT_EQ(packet.service_id(), 0u);
 }
 
-TEST(Server, ProcessPacket_AssignsAnUnassignedChannel) {
-  TestOutput<128> output(1);
-  Channel channels[] = {
-      Channel::Create<1>(&output),
-      Channel::Create<2>(&output),
-      Channel(),
-  };
-  Server server(channels);
-  internal::Service service(42, {});
-  server.RegisterService(service);
-
-  byte encoded_packet[64];
-  constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
-  Packet request = MakePacket(/*channel_id=*/99, 42, 27, payload);
-  auto sws = request.Encode(encoded_packet);
-
+TEST_F(BasicServer, ProcessPacket_UnassignedChannel_AssignsToAvalableSlot) {
   TestOutput<128> unassigned_output(2);
-  server.ProcessPacket(span(encoded_packet, sws.size()), unassigned_output);
-  ASSERT_EQ(channels[2].id(), 99u);
+  server_.ProcessPacket(
+      EncodeRequest(PacketType::RPC, /*channel_id=*/99, 42, 27),
+      unassigned_output);
+  ASSERT_EQ(channels_[2].id(), 99u);
 
   Packet packet = Packet::FromBuffer(unassigned_output.sent_packet());
-  EXPECT_EQ(packet.status(), Status::OK);
   EXPECT_EQ(packet.channel_id(), 99u);
   EXPECT_EQ(packet.service_id(), 42u);
+  EXPECT_EQ(packet.method_id(), 0u);  // No method ID 27
+  EXPECT_EQ(packet.status(), Status::NOT_FOUND);
 }
 
-TEST(Server, ProcessPacket_SendsResourceExhaustedWhenChannelCantBeAssigned) {
-  TestOutput<128> output(1);
-  Channel channels[] = {
-      Channel::Create<1>(&output),
-      Channel::Create<2>(&output),
-  };
-  Server server(channels);
-  internal::Service service(42, {});
-  server.RegisterService(service);
+TEST_F(BasicServer,
+       ProcessPacket_UnassignedChannel_SendsResourceExhaustedIfCannotAssign) {
+  channels_[2] = Channel::Create<3>(&output_);  // Occupy only available channel
 
-  byte encoded_packet[64];
-  constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
-  Packet request = MakePacket(/*channel_id=*/99, 42, 27, payload);
-  auto sws = request.Encode(encoded_packet);
+  server_.ProcessPacket(
+      EncodeRequest(PacketType::RPC, /*channel_id=*/99, 42, 27), output_);
 
-  server.ProcessPacket(span(encoded_packet, sws.size()), output);
-
-  Packet packet = Packet::FromBuffer(output.sent_packet());
+  Packet packet = Packet::FromBuffer(output_.sent_packet());
   EXPECT_EQ(packet.status(), Status::RESOURCE_EXHAUSTED);
   EXPECT_EQ(packet.channel_id(), 0u);
   EXPECT_EQ(packet.service_id(), 0u);