1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <tuple>
17 #include <type_traits>
18 
19 #include "gtest/gtest.h"
20 #include "pw_rpc/internal/packet.h"
21 #include "pw_rpc/internal/raw_method.h"
22 #include "pw_rpc/server_context.h"
23 
24 namespace pw::rpc::internal {
25 namespace {
26 
27 // This class tests Method implementation classes and MethodTraits
28 // specializations. It verifies that they provide the expected functions and
29 // that they correctly identify and construct the various method types.
30 //
31 // The TestService class must inherit from Service and provide the following
32 // methods with valid signatures for RPCs:
33 //
34 //   - Unary: a valid unary RPC member function
35 //   - StaticUnary: valid unary RPC static member function
36 //   - ServerStreaming: valid server streaming RPC member function
37 //   - StaticServerStreaming: valid server streaming static RPC member function
38 //
39 // The class must also provide methods with errors as described in their names:
40 //
41 //   - UnaryWrongArg
42 //   - StaticUnaryVoidReturn
43 //   - ServerStreamingBadReturn
44 //   - StaticServerStreamingMissingArg
45 //
46 template <typename MethodImpl, typename TestService, auto... extra_method_args>
47 struct MethodImplTester {
48   // Test the MethodTraits::kType member.
49   static_assert(MethodTraits<decltype(&TestService::Unary)>::kType ==
50                 MethodType::kUnary);
51   static_assert(MethodTraits<decltype(&TestService::StaticUnary)>::kType ==
52                 MethodType::kUnary);
53   static_assert(MethodTraits<decltype(&TestService::ServerStreaming)>::kType ==
54                 MethodType::kServerStreaming);
55   static_assert(
56       MethodTraits<decltype(&TestService::StaticServerStreaming)>::kType ==
57       MethodType::kServerStreaming);
58 
59   // Test method creation.
60   static constexpr MethodImpl kUnaryMethod =
61       MethodImpl::template Unary<&TestService::Unary>(1, extra_method_args...);
62   static_assert(kUnaryMethod.id() == 1);
63 
64   static constexpr MethodImpl kStaticUnaryMethod =
65       MethodImpl::template Unary<&TestService::StaticUnary>(
66           2, extra_method_args...);
67   static_assert(kStaticUnaryMethod.id() == 2);
68 
69   static constexpr MethodImpl kServerStreamingMethod =
70       MethodImpl::template ServerStreaming<&TestService::ServerStreaming>(
71           3, extra_method_args...);
72   static_assert(kServerStreamingMethod.id() == 3);
73 
74   static constexpr MethodImpl kStaticServerStreamingMethod =
75       MethodImpl::template ServerStreaming<&TestService::StaticServerStreaming>(
76           4, extra_method_args...);
77   static_assert(kStaticServerStreamingMethod.id() == 4);
78 
79   // Test that there is an Invalid method creation function.
80   static constexpr MethodImpl kInvalidMethod = MethodImpl::Invalid();
81   static_assert(kInvalidMethod.id() == 0);
82 
83   // Provide a method that tests can call to ensure this class is instantiated.
MethodImplIsValidMethodImplTester84   bool MethodImplIsValid() const {
85     return true;  // If this class compiles, the MethodImpl passes this test.
86   }
87 };
88 
89 }  // namespace
90 }  // namespace pw::rpc::internal
91