1 // Copyright 2022 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 <cinttypes> 17 18 #include "pb_decode.h" 19 #include "pb_encode.h" 20 #include "pw_rpc/internal/client_server_testing.h" 21 #include "pw_rpc/nanopb/fake_channel_output.h" 22 23 namespace pw::rpc { 24 namespace internal { 25 26 template <size_t kOutputSize, 27 size_t kMaxPackets, 28 size_t kPayloadsBufferSizeBytes> 29 class NanopbForwardingChannelOutput final 30 : public ForwardingChannelOutput< 31 NanopbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes>, 32 kOutputSize, 33 kMaxPackets, 34 kPayloadsBufferSizeBytes> { 35 private: 36 template <auto kMethod> 37 using MethodInfo = internal::MethodInfo<kMethod>; 38 template <auto kMethod> 39 using Response = typename MethodInfo<kMethod>::Response; 40 template <auto kMethod> 41 using Request = typename MethodInfo<kMethod>::Request; 42 43 using Base = ForwardingChannelOutput< 44 NanopbFakeChannelOutput<kMaxPackets, kPayloadsBufferSizeBytes>, 45 kOutputSize, 46 kMaxPackets, 47 kPayloadsBufferSizeBytes>; 48 49 public: 50 constexpr NanopbForwardingChannelOutput( 51 TestPacketProcessor&& server_packet_processor = nullptr, 52 TestPacketProcessor&& client_packet_processor = nullptr) Base(std::move (server_packet_processor),std::move (client_packet_processor))53 : Base(std::move(server_packet_processor), 54 std::move(client_packet_processor)) {} 55 56 template <auto kMethod> response(uint32_t channel_id,uint32_t index)57 Response<kMethod> response(uint32_t channel_id, uint32_t index) { 58 PW_ASSERT(Base::PacketCount() >= index); 59 return Base::output_.template responses<kMethod>(channel_id)[index]; 60 } 61 62 template <auto kMethod> response(uint32_t channel_id,uint32_t index,Response<kMethod> & response)63 void response(uint32_t channel_id, 64 uint32_t index, 65 Response<kMethod>& response) { 66 PW_ASSERT(Base::PacketCount() >= index); 67 auto payloads_view = Base::output_.template responses<kMethod>(channel_id); 68 PW_ASSERT(payloads_view.serde() 69 .Decode(payloads_view.payloads()[index], response) 70 .ok()); 71 } 72 73 template <auto kMethod> request(uint32_t channel_id,uint32_t index)74 Request<kMethod> request(uint32_t channel_id, uint32_t index) { 75 PW_ASSERT(Base::PacketCount() >= index); 76 return Base::output_.template requests<kMethod>(channel_id)[index]; 77 } 78 }; 79 80 } // namespace internal 81 82 template <size_t kOutputSize = 128, 83 size_t kMaxPackets = 16, 84 size_t kPayloadsBufferSizeBytes = 128> 85 class NanopbClientServerTestContext final 86 : public internal::ClientServerTestContext< 87 internal::NanopbForwardingChannelOutput<kOutputSize, 88 kMaxPackets, 89 kPayloadsBufferSizeBytes>, 90 kOutputSize, 91 kMaxPackets, 92 kPayloadsBufferSizeBytes> { 93 private: 94 template <auto kMethod> 95 using MethodInfo = internal::MethodInfo<kMethod>; 96 template <auto kMethod> 97 using Response = typename MethodInfo<kMethod>::Response; 98 template <auto kMethod> 99 using Request = typename MethodInfo<kMethod>::Request; 100 101 using Base = internal::ClientServerTestContext< 102 internal::NanopbForwardingChannelOutput<kOutputSize, 103 kMaxPackets, 104 kPayloadsBufferSizeBytes>, 105 kOutputSize, 106 kMaxPackets, 107 kPayloadsBufferSizeBytes>; 108 109 public: 110 NanopbClientServerTestContext( 111 TestPacketProcessor&& server_packet_processor = nullptr, 112 TestPacketProcessor&& client_packet_processor = nullptr) Base(std::move (server_packet_processor),std::move (client_packet_processor))113 : Base(std::move(server_packet_processor), 114 std::move(client_packet_processor)) {} 115 116 // Retrieve copy of request indexed by order of occurance 117 template <auto kMethod> request(uint32_t index)118 Request<kMethod> request(uint32_t index) { 119 return Base::channel_output_.template request<kMethod>(Base::channel().id(), 120 index); 121 } 122 123 // Retrieve copy of response indexed by order of occurance 124 template <auto kMethod> response(uint32_t index)125 Response<kMethod> response(uint32_t index) { 126 return Base::channel_output_.template response<kMethod>( 127 Base::channel().id(), index); 128 } 129 130 // Gives access to the RPC's indexed by order of occurance using passed 131 // Response object to parse using nanopb. Use this version when you need 132 // to set callback fields in the Response object before parsing. 133 template <auto kMethod> response(uint32_t index,Response<kMethod> & response)134 void response(uint32_t index, Response<kMethod>& response) { 135 return Base::channel_output_.template response<kMethod>( 136 Base::channel().id(), index, response); 137 } 138 }; 139 140 } // namespace pw::rpc 141