pw_rpc: Simplify ServerReader/Writer Open API

- Update the Reader/Writer Open function to take a single, simpler
  template argument.

  Before:

    RawServerWriter::Open<&ServiceNameImpl::MethodName,
                          CalculateMethodId("MethodName")>(...)
  After:

    RawServerWriter::Open<pw_rpc::raw::ServiceName::MethodName>(...)

  This uses the new MethodInfo type to extract information about the
  RPC method, avoiding the need for the user to calculate the method ID.
- Remove the CalculateMethodId() function, which is no longer necessary.
  This keeps method IDs as an implementation detail that is hidden from
  pw_rpc users.
- Add tests for opening responder objects for unary RPCs.

Change-Id: Ifa7cabbc35fa28986df1a2a2449695adb2d24eb2
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/61060
Reviewed-by: Alexei Frolov <frolv@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
diff --git a/pw_rpc/docs.rst b/pw_rpc/docs.rst
index 555fc6a..b379e7b 100644
--- a/pw_rpc/docs.rst
+++ b/pw_rpc/docs.rst
@@ -52,10 +52,23 @@
 reboot. After the reboot, the device opens the writer object and sends its
 response to the client.
 
-.. admonition:: Under construction
+The C++ API for opening a server reader/writer takes the generated RPC function
+as a template parameter. The server to use, channel ID, and service instance are
+passed as arguments. The API is the same for all RPC types, except the
+appropriate reader/writer class must be used.
 
-  The ``ReaderWriter::Open()`` API is cumbersome, but a more streamlined API
-  will be added to the generated RPC code.
+.. code-block:: c++
+
+  // Open a ServerWriter for a server streaming RPC.
+  auto writer = RawServerWriter::Open<pw_rpc::raw::ServiceName::MethodName>(
+      server, channel_id, service_instance);
+
+  // Send some responses, even though the client has not yet called this RPC.
+  CHECK_OK(writer.Write(encoded_response_1));
+  CHECK_OK(writer.Write(encoded_response_2));
+
+  // Finish the RPC.
+  CHECK_OK(writer.Finish(OkStatus()));
 
 Creating an RPC
 ===============
diff --git a/pw_rpc/nanopb/public/pw_rpc/nanopb/server_reader_writer.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/server_reader_writer.h
index 2cc36bf..2e8cbee 100644
--- a/pw_rpc/nanopb/public/pw_rpc/nanopb/server_reader_writer.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/server_reader_writer.h
@@ -20,6 +20,7 @@
 #include "pw_bytes/span.h"
 #include "pw_rpc/channel.h"
 #include "pw_rpc/internal/call.h"
+#include "pw_rpc/internal/method_info.h"
 #include "pw_rpc/internal/method_lookup.h"
 #include "pw_rpc/internal/open_call.h"
 #include "pw_rpc/server.h"
@@ -98,21 +99,23 @@
   // Creates a NanopbServerReaderWriter that is ready to send responses for a
   // particular RPC. This can be used for testing or to send responses to an RPC
   // that has not been started by a client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static NanopbServerReaderWriter Open(Server& server,
                                                      uint32_t channel_id,
                                                      ServiceImpl& service) {
-    static_assert(std::is_same_v<Request, internal::Request<kMethod>>,
+    using Info = internal::MethodInfo<kMethod>;
+    static_assert(std::is_same_v<Request, typename Info::Request>,
                   "The request type of a NanopbServerReaderWriter must match "
                   "the method.");
-    static_assert(std::is_same_v<Response, internal::Response<kMethod>>,
+    static_assert(std::is_same_v<Response, typename Info::Response>,
                   "The response type of a NanopbServerReaderWriter must match "
                   "the method.");
-    return {internal::OpenCall<kMethod, MethodType::kBidirectionalStreaming>(
+    return {internal::OpenContext<kMethod, MethodType::kBidirectionalStreaming>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetNanopbMethod<ServiceImpl,
+                                                Info::kMethodId>())};
   }
 
   constexpr NanopbServerReaderWriter()
@@ -166,21 +169,23 @@
   // Creates a NanopbServerReader that is ready to send a response to a
   // particular RPC. This can be used for testing or to finish an RPC that has
   // not been started by the client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static NanopbServerReader Open(Server& server,
                                                uint32_t channel_id,
                                                ServiceImpl& service) {
+    using Info = internal::MethodInfo<kMethod>;
     static_assert(
-        std::is_same_v<Request, internal::Request<kMethod>>,
+        std::is_same_v<Request, typename Info::Request>,
         "The request type of a NanopbServerReader must match the method.");
     static_assert(
-        std::is_same_v<Response, internal::Response<kMethod>>,
+        std::is_same_v<Response, typename Info::Response>,
         "The response type of a NanopbServerReader must match the method.");
-    return {internal::OpenCall<kMethod, MethodType::kClientStreaming>(
+    return {internal::OpenContext<kMethod, MethodType::kClientStreaming>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetNanopbMethod<ServiceImpl,
+                                                Info::kMethodId>())};
   }
 
   // Allow default construction so that users can declare a variable into which
@@ -224,18 +229,20 @@
   // Creates a NanopbServerWriter that is ready to send responses for a
   // particular RPC. This can be used for testing or to send responses to an RPC
   // that has not been started by a client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static NanopbServerWriter Open(Server& server,
                                                uint32_t channel_id,
                                                ServiceImpl& service) {
+    using Info = internal::MethodInfo<kMethod>;
     static_assert(
-        std::is_same_v<Response, internal::Response<kMethod>>,
+        std::is_same_v<Response, typename Info::Response>,
         "The response type of a NanopbServerWriter must match the method.");
-    return {internal::OpenCall<kMethod, MethodType::kServerStreaming>(
+    return {internal::OpenContext<kMethod, MethodType::kServerStreaming>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetNanopbMethod<ServiceImpl,
+                                                Info::kMethodId>())};
   }
 
   // Allow default construction so that users can declare a variable into which
@@ -282,18 +289,20 @@
   // Creates a NanopbServerResponder that is ready to send a response for a
   // particular RPC. This can be used for testing or to send responses to an RPC
   // that has not been started by a client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static NanopbServerResponder Open(Server& server,
                                                   uint32_t channel_id,
                                                   ServiceImpl& service) {
+    using Info = internal::MethodInfo<kMethod>;
     static_assert(
-        std::is_same_v<Response, internal::Response<kMethod>>,
+        std::is_same_v<Response, typename Info::Response>,
         "The response type of a NanopbServerResponder must match the method.");
-    return {internal::OpenCall<kMethod, MethodType::kUnary>(
+    return {internal::OpenContext<kMethod, MethodType::kUnary>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetNanopbMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetNanopbMethod<ServiceImpl,
+                                                Info::kMethodId>())};
   }
 
   // Allow default construction so that users can declare a variable into which
diff --git a/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h b/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h
index 77874cd..51269a0 100644
--- a/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h
+++ b/pw_rpc/nanopb/public/pw_rpc/nanopb/test_method_context.h
@@ -71,10 +71,10 @@
 //   PW_NANOPB_TEST_METHOD_CONTEXT(MyService, BestMethod, 3, 256) context;
 //   ASSERT_EQ(3u, context.responses().max_size());
 //
-#define PW_NANOPB_TEST_METHOD_CONTEXT(service, method, ...)                \
-  ::pw::rpc::NanopbTestMethodContext<service,                              \
-                                     &service::method,                     \
-                                     ::pw::rpc::CalculateMethodId(#method) \
+#define PW_NANOPB_TEST_METHOD_CONTEXT(service, method, ...)             \
+  ::pw::rpc::NanopbTestMethodContext<service,                           \
+                                     &service::method,                  \
+                                     ::pw::rpc::internal::Hash(#method) \
                                          PW_COMMA_ARGS(__VA_ARGS__)>
 template <typename Service,
           auto kMethod,
diff --git a/pw_rpc/nanopb/server_reader_writer_test.cc b/pw_rpc/nanopb/server_reader_writer_test.cc
index ad624d9..a508631 100644
--- a/pw_rpc/nanopb/server_reader_writer_test.cc
+++ b/pw_rpc/nanopb/server_reader_writer_test.cc
@@ -21,7 +21,8 @@
 
 namespace pw::rpc {
 
-class TestService final : public test::generated::TestService<TestService> {
+class TestServiceImpl final
+    : public test::generated::TestService<TestServiceImpl> {
  public:
   Status TestUnaryRpc(ServerContext&,
                       const pw_rpc_test_TestRequest&,
@@ -49,28 +50,43 @@
                                pw_rpc_test_TestStreamResponse>&) {}
 };
 
-template <auto kMethod, uint32_t kMethodId>
+template <auto kMethod>
 struct ReaderWriterTestContext {
+  using Info = internal::MethodInfo<kMethod>;
+
   ReaderWriterTestContext()
-      : output(decltype(output)::
-                   template Create<TestService, kMethod, kMethodId>()),
+      : output(decltype(output)::template Create<
+               TestServiceImpl,
+               Info::template Function<TestServiceImpl>(),
+               Info::kMethodId>()),
         channel(Channel::Create<1>(&output)),
         server(std::span(&channel, 1)) {}
 
-  TestService service;
-  NanopbFakeChannelOutput<internal::Response<kMethod>, 4, 128> output;
+  TestServiceImpl service;
+  NanopbFakeChannelOutput<typename Info::Response, 4, 128> output;
   Channel channel;
   Server server;
 };
 
+using test::pw_rpc::nanopb::TestService;
+
+TEST(NanopbServerResponder, Open_ReturnsUsableResponder) {
+  ReaderWriterTestContext<TestService::TestUnaryRpc> ctx;
+  NanopbServerResponder responder =
+      NanopbServerResponder<pw_rpc_test_TestResponse>::Open<
+          TestService::TestUnaryRpc>(ctx.server, ctx.channel.id(), ctx.service);
+
+  responder.Finish({.value = 4321});
+
+  EXPECT_EQ(ctx.output.last_response().value, 4321);
+  EXPECT_EQ(ctx.output.last_status(), OkStatus());
+}
+
 TEST(NanopbServerWriter, Open_ReturnsUsableWriter) {
-  ReaderWriterTestContext<&TestService::TestServerStreamRpc,
-                          CalculateMethodId("TestServerStreamRpc")>
-      ctx;
+  ReaderWriterTestContext<TestService::TestServerStreamRpc> ctx;
   NanopbServerWriter responder =
       NanopbServerWriter<pw_rpc_test_TestStreamResponse>::Open<
-          &TestService::TestServerStreamRpc,
-          CalculateMethodId("TestServerStreamRpc")>(
+          TestService::TestServerStreamRpc>(
           ctx.server, ctx.channel.id(), ctx.service);
 
   responder.Write({.chunk = {}, .number = 321});
@@ -81,14 +97,11 @@
 }
 
 TEST(NanopbServerReader, Open_ReturnsUsableReader) {
-  ReaderWriterTestContext<&TestService::TestClientStreamRpc,
-                          CalculateMethodId("TestClientStreamRpc")>
-      ctx;
+  ReaderWriterTestContext<TestService::TestClientStreamRpc> ctx;
   NanopbServerReader responder =
       NanopbServerReader<pw_rpc_test_TestRequest,
                          pw_rpc_test_TestStreamResponse>::
-          Open<&TestService::TestClientStreamRpc,
-               CalculateMethodId("TestClientStreamRpc")>(
+          Open<TestService::TestClientStreamRpc>(
               ctx.server, ctx.channel.id(), ctx.service);
 
   responder.Finish({.chunk = {}, .number = 321});
@@ -97,14 +110,11 @@
 }
 
 TEST(NanopbServerReaderWriter, Open_ReturnsUsableReaderWriter) {
-  ReaderWriterTestContext<&TestService::TestBidirectionalStreamRpc,
-                          CalculateMethodId("TestBidirectionalStreamRpc")>
-      ctx;
+  ReaderWriterTestContext<TestService::TestBidirectionalStreamRpc> ctx;
   NanopbServerReaderWriter responder =
       NanopbServerReaderWriter<pw_rpc_test_TestRequest,
                                pw_rpc_test_TestStreamResponse>::
-          Open<&TestService::TestBidirectionalStreamRpc,
-               CalculateMethodId("TestBidirectionalStreamRpc")>(
+          Open<TestService::TestBidirectionalStreamRpc>(
               ctx.server, ctx.channel.id(), ctx.service);
 
   responder.Write({.chunk = {}, .number = 321});
diff --git a/pw_rpc/public/pw_rpc/internal/open_call.h b/pw_rpc/public/pw_rpc/internal/open_call.h
index 2578b03..d784462 100644
--- a/pw_rpc/public/pw_rpc/internal/open_call.h
+++ b/pw_rpc/public/pw_rpc/internal/open_call.h
@@ -24,24 +24,28 @@
 
 // Creates a call context for a particular RPC. Unlike the CallContext
 // constructor, this function checks the type of RPC at compile time.
-template <auto kMethod, MethodType kExpected, typename MethodImpl>
-CallContext OpenCall(Server& server,
-                     uint32_t channel_id,
-                     Service& service,
-                     const MethodImpl& method) {
+template <auto kMethod,
+          MethodType kExpected,
+          typename ServiceImpl,
+          typename MethodImpl>
+CallContext OpenContext(Server& server,
+                        uint32_t channel_id,
+                        ServiceImpl& service,
+                        const MethodImpl& method) {
+  using Info = internal::MethodInfo<kMethod>;
   if constexpr (kExpected == MethodType::kUnary) {
-    static_assert(internal::MethodTraits<decltype(kMethod)>::kType == kExpected,
+    static_assert(Info::kType == kExpected,
                   "ServerResponse objects may only be opened for unary RPCs.");
   } else if constexpr (kExpected == MethodType::kServerStreaming) {
     static_assert(
-        MethodTraits<decltype(kMethod)>::kType == kExpected,
+        Info::kType == kExpected,
         "ServerWriters may only be opened for server streaming RPCs.");
   } else if constexpr (kExpected == MethodType::kClientStreaming) {
     static_assert(
-        MethodTraits<decltype(kMethod)>::kType == kExpected,
+        Info::kType == kExpected,
         "ServerReaders may only be opened for client streaming RPCs.");
   } else if constexpr (kExpected == MethodType::kBidirectionalStreaming) {
-    static_assert(internal::MethodTraits<decltype(kMethod)>::kType == kExpected,
+    static_assert(Info::kType == kExpected,
                   "ServerReaderWriters may only be opened for bidirectional "
                   "streaming RPCs.");
   }
diff --git a/pw_rpc/public/pw_rpc/service.h b/pw_rpc/public/pw_rpc/service.h
index 5dd1288..a4f2dbf 100644
--- a/pw_rpc/public/pw_rpc/service.h
+++ b/pw_rpc/public/pw_rpc/service.h
@@ -19,7 +19,6 @@
 
 #include "pw_containers/intrusive_list.h"
 #include "pw_preprocessor/compiler.h"
-#include "pw_rpc/internal/hash.h"
 #include "pw_rpc/internal/method.h"
 #include "pw_rpc/internal/method_union.h"
 
@@ -73,10 +72,4 @@
   const uint16_t method_count_;
 };
 
-// Calculates the method ID of the method with the given name. Services track
-// methods by this ID.
-constexpr uint32_t CalculateMethodId(std::string_view method_name) {
-  return internal::Hash(method_name);
-}
-
 }  // namespace pw::rpc
diff --git a/pw_rpc/raw/public/pw_rpc/raw/server_reader_writer.h b/pw_rpc/raw/public/pw_rpc/raw/server_reader_writer.h
index c973d85..4abed67 100644
--- a/pw_rpc/raw/public/pw_rpc/raw/server_reader_writer.h
+++ b/pw_rpc/raw/public/pw_rpc/raw/server_reader_writer.h
@@ -20,6 +20,7 @@
 #include "pw_bytes/span.h"
 #include "pw_rpc/channel.h"
 #include "pw_rpc/internal/call.h"
+#include "pw_rpc/internal/method_info.h"
 #include "pw_rpc/internal/method_lookup.h"
 #include "pw_rpc/internal/open_call.h"
 #include "pw_rpc/server.h"
@@ -54,15 +55,17 @@
   // Creates a RawServerReaderWriter that is ready to send responses for a
   // particular RPC. This can be used for testing or to send responses to an RPC
   // that has not been started by a client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static RawServerReaderWriter Open(Server& server,
                                                   uint32_t channel_id,
                                                   ServiceImpl& service) {
-    return {internal::OpenCall<kMethod, MethodType::kBidirectionalStreaming>(
+    return {internal::OpenContext<kMethod, MethodType::kBidirectionalStreaming>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetRawMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetRawMethod<
+            ServiceImpl,
+            internal::MethodInfo<kMethod>::kMethodId>())};
   }
 
   using internal::Call::active;
@@ -113,15 +116,17 @@
   // Creates a RawServerReader that is ready to send a response to a particular
   // RPC. This can be used for testing or to finish an RPC that has not been
   // started by the client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static RawServerReader Open(Server& server,
                                             uint32_t channel_id,
                                             ServiceImpl& service) {
-    return {internal::OpenCall<kMethod, MethodType::kClientStreaming>(
+    return {internal::OpenContext<kMethod, MethodType::kClientStreaming>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetRawMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetRawMethod<
+            ServiceImpl,
+            internal::MethodInfo<kMethod>::kMethodId>())};
   }
 
   constexpr RawServerReader()
@@ -159,15 +164,17 @@
   // Creates a RawServerWriter that is ready to send responses for a particular
   // RPC. This can be used for testing or to send responses to an RPC that has
   // not been started by a client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static RawServerWriter Open(Server& server,
                                             uint32_t channel_id,
                                             ServiceImpl& service) {
-    return {internal::OpenCall<kMethod, MethodType::kServerStreaming>(
+    return {internal::OpenContext<kMethod, MethodType::kServerStreaming>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetRawMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetRawMethod<
+            ServiceImpl,
+            internal::MethodInfo<kMethod>::kMethodId>())};
   }
 
   constexpr RawServerWriter()
@@ -203,15 +210,17 @@
   // Creates a RawServerResponder that is ready to send responses for a
   // particular RPC. This can be used for testing or to send responses to an RPC
   // that has not been started by a client.
-  template <auto kMethod, uint32_t kMethodId, typename ServiceImpl>
+  template <auto kMethod, typename ServiceImpl>
   [[nodiscard]] static RawServerResponder Open(Server& server,
                                                uint32_t channel_id,
                                                ServiceImpl& service) {
-    return {internal::OpenCall<kMethod, MethodType::kUnary>(
+    return {internal::OpenContext<kMethod, MethodType::kUnary>(
         server,
         channel_id,
         service,
-        internal::MethodLookup::GetRawMethod<ServiceImpl, kMethodId>())};
+        internal::MethodLookup::GetRawMethod<
+            ServiceImpl,
+            internal::MethodInfo<kMethod>::kMethodId>())};
   }
 
   constexpr RawServerResponder() : RawServerReaderWriter(MethodType::kUnary) {}
diff --git a/pw_rpc/raw/public/pw_rpc/raw/test_method_context.h b/pw_rpc/raw/public/pw_rpc/raw/test_method_context.h
index 0e0825d..afe9edc 100644
--- a/pw_rpc/raw/public/pw_rpc/raw/test_method_context.h
+++ b/pw_rpc/raw/public/pw_rpc/raw/test_method_context.h
@@ -74,10 +74,10 @@
 //   PW_RAW_TEST_METHOD_CONTEXT(MyService, BestMethod, 3, 256) context;
 //   ASSERT_EQ(3u, context.responses().max_size());
 //
-#define PW_RAW_TEST_METHOD_CONTEXT(service, method, ...)                \
-  ::pw::rpc::RawTestMethodContext<service,                              \
-                                  &service::method,                     \
-                                  ::pw::rpc::CalculateMethodId(#method) \
+#define PW_RAW_TEST_METHOD_CONTEXT(service, method, ...)             \
+  ::pw::rpc::RawTestMethodContext<service,                           \
+                                  &service::method,                  \
+                                  ::pw::rpc::internal::Hash(#method) \
                                       PW_COMMA_ARGS(__VA_ARGS__)>
 template <typename Service,
           auto kMethod,
diff --git a/pw_rpc/raw/server_reader_writer_test.cc b/pw_rpc/raw/server_reader_writer_test.cc
index ab12a6f..472f378 100644
--- a/pw_rpc/raw/server_reader_writer_test.cc
+++ b/pw_rpc/raw/server_reader_writer_test.cc
@@ -21,7 +21,8 @@
 
 namespace pw::rpc {
 
-class TestService final : public test::generated::TestService<TestService> {
+class TestServiceImpl final
+    : public test::generated::TestService<TestServiceImpl> {
  public:
   static StatusWithSize TestUnaryRpc(ServerContext&, ConstByteSpan, ByteSpan) {
     return StatusWithSize(0);
@@ -43,17 +44,30 @@
         channel(Channel::Create<1>(&output)),
         server(std::span(&channel, 1)) {}
 
-  TestService service;
+  TestServiceImpl service;
   RawFakeChannelOutput<128, 4> output;
   Channel channel;
   Server server;
 };
 
+using test::pw_rpc::raw::TestService;
+
+TEST(RawServerResponder, Open_ReturnsUsableResponder) {
+  ReaderWriterTestContext ctx(MethodType::kUnary);
+  RawServerResponder call = RawServerResponder::Open<TestService::TestUnaryRpc>(
+      ctx.server, ctx.channel.id(), ctx.service);
+
+  EXPECT_EQ(call.channel_id(), ctx.channel.id());
+  call.Finish(std::as_bytes(std::span("hello from pw_rpc")));
+
+  EXPECT_STREQ(reinterpret_cast<const char*>(ctx.output.last_response().data()),
+               "hello from pw_rpc");
+}
+
 TEST(RawServerWriter, Open_ReturnsUsableWriter) {
   ReaderWriterTestContext ctx(MethodType::kServerStreaming);
   RawServerWriter call =
-      RawServerWriter::Open<&TestService::TestServerStreamRpc,
-                            CalculateMethodId("TestServerStreamRpc")>(
+      RawServerWriter::Open<TestService::TestServerStreamRpc>(
           ctx.server, ctx.channel.id(), ctx.service);
 
   EXPECT_EQ(call.channel_id(), ctx.channel.id());
@@ -66,8 +80,7 @@
 TEST(RawServerReader, Open_ReturnsUsableReader) {
   ReaderWriterTestContext ctx(MethodType::kClientStreaming);
   RawServerReader call =
-      RawServerReader::Open<&TestService::TestClientStreamRpc,
-                            CalculateMethodId("TestClientStreamRpc")>(
+      RawServerReader::Open<TestService::TestClientStreamRpc>(
           ctx.server, ctx.channel.id(), ctx.service);
 
   EXPECT_EQ(call.channel_id(), ctx.channel.id());
@@ -80,9 +93,7 @@
 TEST(RawServerReaderWriter, Open_ReturnsUsableReaderWriter) {
   ReaderWriterTestContext ctx(MethodType::kBidirectionalStreaming);
   RawServerReaderWriter call =
-      RawServerReaderWriter::Open<&TestService::TestBidirectionalStreamRpc,
-                                  CalculateMethodId(
-                                      "TestBidirectionalStreamRpc")>(
+      RawServerReaderWriter::Open<TestService::TestBidirectionalStreamRpc>(
           ctx.server, ctx.channel.id(), ctx.service);
 
   EXPECT_EQ(call.channel_id(), ctx.channel.id());